moved files to thermo subdirectory
This commit is contained in:
parent
95b303ddbd
commit
a04e7309a2
60 changed files with 16812 additions and 16 deletions
143
Cantera/src/thermo/ConstCpPoly.cpp
Normal file
143
Cantera/src/thermo/ConstCpPoly.cpp
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
/**
|
||||
* @file ConstCpPoly.cpp
|
||||
* Declarations for the \link Cantera::SpeciesThermoInterpType SpeciesThermoInterpType \endlink object that
|
||||
* employs a constant heat capacity assumption (see \ref spthermo and
|
||||
* \link Cantera::ConstCpPoly ConstCpPoly \endlink).
|
||||
*/
|
||||
/*
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
// Copyright 2001 California Institute of Technology
|
||||
|
||||
|
||||
|
||||
#include "ConstCpPoly.h"
|
||||
#include <math.h>
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
ConstCpPoly::ConstCpPoly()
|
||||
: m_t0(0.0),
|
||||
m_cp0_R(0.0),
|
||||
m_h0_R(0.0),
|
||||
m_s0_R(0.0),
|
||||
m_logt0(0.0),
|
||||
m_lowT(0.0),
|
||||
m_highT(0.0),
|
||||
m_Pref(0.0),
|
||||
m_index(0) {
|
||||
}
|
||||
|
||||
ConstCpPoly::ConstCpPoly(int n, doublereal tlow, doublereal thigh,
|
||||
doublereal pref,
|
||||
const doublereal* coeffs) :
|
||||
m_lowT (tlow),
|
||||
m_highT (thigh),
|
||||
m_Pref (pref),
|
||||
m_index (n) {
|
||||
m_t0 = coeffs[0];
|
||||
m_h0_R = coeffs[1] / GasConstant;
|
||||
m_s0_R = coeffs[2] / GasConstant;
|
||||
m_cp0_R = coeffs[3] / GasConstant;
|
||||
m_logt0 = log(m_t0);
|
||||
}
|
||||
|
||||
ConstCpPoly::ConstCpPoly(const ConstCpPoly& b) :
|
||||
m_t0 (b.m_t0),
|
||||
m_cp0_R (b.m_cp0_R),
|
||||
m_h0_R (b.m_h0_R),
|
||||
m_s0_R (b.m_s0_R),
|
||||
m_logt0 (b.m_logt0),
|
||||
m_lowT (b.m_lowT),
|
||||
m_highT (b.m_highT),
|
||||
m_Pref (b.m_Pref),
|
||||
m_index (b.m_index)
|
||||
{
|
||||
}
|
||||
|
||||
ConstCpPoly& ConstCpPoly::operator=(const ConstCpPoly& b) {
|
||||
if (&b != this) {
|
||||
m_t0 = b.m_t0;
|
||||
m_cp0_R = b.m_cp0_R;
|
||||
m_h0_R = b.m_h0_R;
|
||||
m_s0_R = b.m_s0_R;
|
||||
m_logt0 = b.m_logt0;
|
||||
m_lowT = b.m_lowT;
|
||||
m_highT = b.m_highT;
|
||||
m_Pref = b.m_Pref;
|
||||
m_index = b.m_index;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ConstCpPoly::~ConstCpPoly(){}
|
||||
|
||||
SpeciesThermoInterpType *
|
||||
ConstCpPoly::duplMyselfAsSpeciesThermoInterpType() const {
|
||||
ConstCpPoly* newCCP = new ConstCpPoly(*this);
|
||||
return (SpeciesThermoInterpType*) newCCP;
|
||||
}
|
||||
|
||||
doublereal ConstCpPoly::minTemp() const {
|
||||
return m_lowT;
|
||||
}
|
||||
doublereal ConstCpPoly::maxTemp() const {
|
||||
return m_highT;
|
||||
}
|
||||
doublereal ConstCpPoly::refPressure() const {
|
||||
return m_Pref;
|
||||
}
|
||||
|
||||
void ConstCpPoly::updateProperties(const doublereal* tt,
|
||||
doublereal* cp_R,
|
||||
doublereal* h_RT,
|
||||
doublereal* s_R) const {
|
||||
double t = *tt;
|
||||
doublereal logt = log(t);
|
||||
doublereal rt = 1.0/t;
|
||||
cp_R[m_index] = m_cp0_R;
|
||||
h_RT[m_index] = rt*(m_h0_R + (t - m_t0) * m_cp0_R);
|
||||
s_R[m_index] = m_s0_R + m_cp0_R * (logt - m_logt0);
|
||||
}
|
||||
|
||||
void ConstCpPoly::updatePropertiesTemp(const doublereal temp,
|
||||
doublereal* cp_R,
|
||||
doublereal* h_RT,
|
||||
doublereal* s_R) const {
|
||||
doublereal logt = log(temp);
|
||||
doublereal rt = 1.0/temp;
|
||||
cp_R[m_index] = m_cp0_R;
|
||||
h_RT[m_index] = rt*(m_h0_R + (temp - m_t0) * m_cp0_R);
|
||||
s_R[m_index] = m_s0_R + m_cp0_R * (logt - m_logt0);
|
||||
}
|
||||
|
||||
void ConstCpPoly::reportParameters(int &n, int &type,
|
||||
doublereal &tlow, doublereal &thigh,
|
||||
doublereal &pref,
|
||||
doublereal* const coeffs) const {
|
||||
n = m_index;
|
||||
type = CONSTANT_CP;
|
||||
tlow = m_lowT;
|
||||
thigh = m_highT;
|
||||
pref = m_Pref;
|
||||
coeffs[0] = m_t0;
|
||||
coeffs[1] = m_h0_R * GasConstant;
|
||||
coeffs[2] = m_s0_R * GasConstant;
|
||||
coeffs[3] = m_cp0_R * GasConstant;
|
||||
}
|
||||
|
||||
void ConstCpPoly::modifyParameters(doublereal* coeffs) {
|
||||
m_t0 = coeffs[0];
|
||||
m_h0_R = coeffs[1] / GasConstant;
|
||||
m_s0_R = coeffs[2] / GasConstant;
|
||||
m_cp0_R = coeffs[3] / GasConstant;
|
||||
m_logt0 = log(m_t0);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
196
Cantera/src/thermo/ConstCpPoly.h
Normal file
196
Cantera/src/thermo/ConstCpPoly.h
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
/**
|
||||
* @file ConstCpPoly.h
|
||||
* Headers for the \link Cantera::SpeciesThermoInterpType SpeciesThermoInterpType\endlink
|
||||
* object that employs a constant heat capacity assumption (see \ref spthermo and
|
||||
* \link Cantera::ConstCpPoly ConstCpPoly\endlink).
|
||||
*/
|
||||
/*
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
// Copyright 2001 California Institute of Technology
|
||||
|
||||
|
||||
#ifndef CT_CONSTCPPOLY_H
|
||||
#define CT_CONSTCPPOLY_H
|
||||
|
||||
#include "SpeciesThermoInterpType.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
/**
|
||||
* A constant-heat capacity species thermodynamic property manager class.
|
||||
* This makes the
|
||||
* assumption that the heat capacity is a constant. Then, the following
|
||||
* relations are used to complete the specification of the thermodynamic
|
||||
* functions for the species.
|
||||
*
|
||||
* \f[
|
||||
* \frac{c_p(T)}{R} = Cp0\_R
|
||||
* \f]
|
||||
* \f[
|
||||
* \frac{h^0(T)}{RT} = \frac{1}{T} * (h0\_R + (T - T_0) * Cp0\_R)
|
||||
* \f]
|
||||
* \f[
|
||||
* \frac{s^0(T)}{R} = (s0\_R + (log(T) - log(T_0)) * Cp0\_R)
|
||||
* \f]
|
||||
*
|
||||
* This parameterization takes 4 input values. These are:
|
||||
* - c[0] = \f$ T_0 \f$(Kelvin)
|
||||
* - c[1] = \f$ H_k^o(T_0, p_{ref}) \f$ (J/kmol)
|
||||
* - c[2] = \f$ S_k^o(T_0, p_{ref}) \f$ (J/kmol K)
|
||||
* - c[3] = \f$ {Cp}_k^o(T_0, p_{ref}) \f$ (J(kmol K)
|
||||
*
|
||||
* The multispecies SimpleThermo class makes the same assumptions as
|
||||
* this class does.
|
||||
*
|
||||
* @see SimpleThermo
|
||||
*
|
||||
* @ingroup spthermo
|
||||
*/
|
||||
class ConstCpPoly: public SpeciesThermoInterpType {
|
||||
|
||||
public:
|
||||
|
||||
//! empty constructor
|
||||
ConstCpPoly();
|
||||
|
||||
//! Constructor used in templated instantiations
|
||||
/*!
|
||||
* @param n Species index
|
||||
* @param tlow Minimum temperature
|
||||
* @param thigh Maximum temperature
|
||||
* @param pref reference pressure (Pa).
|
||||
* @param coeffs Vector of coefficients used to set the
|
||||
* parameters for the standard state for species n.
|
||||
* There are 4 coefficients for the %ConstCpPoly parameterization.
|
||||
* - c[0] = \f$ T_0 \f$(Kelvin)
|
||||
* - c[1] = \f$ H_k^o(T_0, p_{ref}) \f$ (J/kmol)
|
||||
* - c[2] = \f$ S_k^o(T_0, p_{ref}) \f$ (J/kmol K)
|
||||
* - c[3] = \f$ {Cp}_k^o(T_0, p_{ref}) \f$ (J(kmol K)
|
||||
*
|
||||
*/
|
||||
ConstCpPoly(int n, doublereal tlow, doublereal thigh,
|
||||
doublereal pref,
|
||||
const doublereal* coeffs);
|
||||
|
||||
//! copy constructor
|
||||
ConstCpPoly(const ConstCpPoly&);
|
||||
|
||||
//! Assignment operator
|
||||
ConstCpPoly& operator=(const ConstCpPoly&);
|
||||
|
||||
//! Destructor
|
||||
virtual ~ConstCpPoly();
|
||||
|
||||
//! Duplicator
|
||||
virtual SpeciesThermoInterpType *
|
||||
duplMyselfAsSpeciesThermoInterpType() const;
|
||||
//! Returns the minimum temperature that the thermo
|
||||
//! parameterization is valid
|
||||
doublereal minTemp() const;
|
||||
|
||||
//! Returns the maximum temperature that the thermo
|
||||
//! parameterization is valid
|
||||
doublereal maxTemp() const;
|
||||
|
||||
//! Returns the reference pressure (Pa)
|
||||
doublereal refPressure() const;
|
||||
|
||||
//! Returns an integer representing the type of parameterization
|
||||
virtual int reportType() const { return CONSTANT_CP; }
|
||||
|
||||
//! Update the properties for this species, given a temperature polynomial
|
||||
/*!
|
||||
* This method is called with a pointer to an array containing the functions of
|
||||
* temperature needed by this parameterization, and three pointers to arrays where the
|
||||
* computed property values should be written. This method updates only one value in
|
||||
* each array.
|
||||
*
|
||||
* Form and Length of the temperature polynomial:
|
||||
* - m_t[0] = tt;
|
||||
*
|
||||
* @param tt Vector of temperature polynomials
|
||||
* @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).
|
||||
*/
|
||||
void updateProperties(const doublereal* tt,
|
||||
doublereal* cp_R, doublereal* h_RT,
|
||||
doublereal* s_R) const;
|
||||
|
||||
//! Compute the reference-state property of one species
|
||||
/*!
|
||||
* Given temperature T in K, this method updates the values of
|
||||
* the non-dimensional heat capacity at constant pressure,
|
||||
* enthalpy, and entropy, at the reference pressure, Pref
|
||||
* of one of the species. The species index is used
|
||||
* to reference into the cp_R, h_RT, and s_R arrays.
|
||||
*
|
||||
* @param temp 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).
|
||||
*/
|
||||
void updatePropertiesTemp(const doublereal temp,
|
||||
doublereal* cp_R, doublereal* h_RT,
|
||||
doublereal* s_R) const;
|
||||
//!This utility function reports back the type of
|
||||
//! parameterization and all of the parameters for the
|
||||
//! species, index.
|
||||
/*!
|
||||
* All parameters are output variables
|
||||
*
|
||||
* @param n Species index
|
||||
* @param type Integer type of the standard type
|
||||
* @param tlow output - Minimum temperature
|
||||
* @param thigh output - Maximum temperature
|
||||
* @param pref output - reference pressure (Pa).
|
||||
* @param coeffs Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
*/
|
||||
void reportParameters(int &n, int &type,
|
||||
doublereal &tlow, doublereal &thigh,
|
||||
doublereal &pref,
|
||||
doublereal* const coeffs) const;
|
||||
//! Modify parameters for the standard state
|
||||
/*!
|
||||
* @param coeffs Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
*/
|
||||
virtual void modifyParameters(doublereal* coeffs);
|
||||
|
||||
protected:
|
||||
//! Base temperature
|
||||
doublereal m_t0;
|
||||
//! Dimensionless value of the heat capacity
|
||||
doublereal m_cp0_R;
|
||||
//! dimensionless value of the enthaply at t0
|
||||
doublereal m_h0_R;
|
||||
//! Dimensionless value of the entropy at t0
|
||||
doublereal m_s0_R;
|
||||
//! log of the t0 value
|
||||
doublereal m_logt0;
|
||||
//! Minimum temperature for which the parameterization is valid (Kelvin)
|
||||
doublereal m_lowT;
|
||||
//! Maximum temperature for which the parameterization is valid (Kelvin)
|
||||
doublereal m_highT;
|
||||
//! Reference pressure (Pa)
|
||||
doublereal m_Pref;
|
||||
//! Species Index
|
||||
int m_index;
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
151
Cantera/src/thermo/ConstDensityThermo.cpp
Executable file
151
Cantera/src/thermo/ConstDensityThermo.cpp
Executable file
|
|
@ -0,0 +1,151 @@
|
|||
/**
|
||||
* @file ConstDensityThermo.cpp
|
||||
* Declarations for a Thermo manager for incompressible ThermoPhases
|
||||
* (see \ref thermoprops and \link Cantera::ConstDensityThermo ConstDensityThermo
|
||||
\endlink).
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright 2002 California Institute of Technology
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma warning(disable:4786)
|
||||
#pragma warning(disable:4503)
|
||||
#endif
|
||||
|
||||
#include "ct_defs.h"
|
||||
#include "mix_defs.h"
|
||||
#include "ConstDensityThermo.h"
|
||||
#include "SpeciesThermo.h"
|
||||
#include <math.h>
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
int ConstDensityThermo::
|
||||
eosType() const { return cIncompressible; }
|
||||
|
||||
doublereal ConstDensityThermo::enthalpy_mole() const {
|
||||
doublereal p0 = m_spthermo->refPressure();
|
||||
return GasConstant * temperature() *
|
||||
mean_X(&enthalpy_RT()[0])
|
||||
+ (pressure() - p0)/molarDensity();
|
||||
}
|
||||
|
||||
doublereal ConstDensityThermo::intEnergy_mole() const {
|
||||
doublereal p0 = m_spthermo->refPressure();
|
||||
return GasConstant * temperature() *
|
||||
mean_X(&enthalpy_RT()[0])
|
||||
- p0/molarDensity();
|
||||
}
|
||||
|
||||
doublereal ConstDensityThermo::entropy_mole() const {
|
||||
return GasConstant * (mean_X(&entropy_R()[0]) -
|
||||
sum_xlogx());
|
||||
}
|
||||
|
||||
doublereal ConstDensityThermo::gibbs_mole() const {
|
||||
return enthalpy_mole() - temperature() * entropy_mole();
|
||||
}
|
||||
|
||||
doublereal ConstDensityThermo::cp_mole() const {
|
||||
return GasConstant * mean_X(&cp_R()[0]);
|
||||
}
|
||||
|
||||
doublereal ConstDensityThermo::cv_mole() const {
|
||||
return cp_mole();
|
||||
}
|
||||
|
||||
doublereal ConstDensityThermo::pressure() const {
|
||||
return m_press;
|
||||
}
|
||||
|
||||
void ConstDensityThermo::setPressure(doublereal p) {
|
||||
m_press = p;
|
||||
}
|
||||
|
||||
void ConstDensityThermo::getActivityConcentrations(doublereal* c) const {
|
||||
getConcentrations(c);
|
||||
}
|
||||
|
||||
void ConstDensityThermo::getActivityCoefficients(doublereal* ac) const {
|
||||
for (int k = 0; k < m_kk; k++) {
|
||||
ac[k] = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
doublereal ConstDensityThermo::standardConcentration(int k) const {
|
||||
return molarDensity();
|
||||
}
|
||||
|
||||
doublereal ConstDensityThermo::logStandardConc(int k) const {
|
||||
return log(molarDensity());
|
||||
}
|
||||
|
||||
void ConstDensityThermo::getChemPotentials(doublereal* mu) const {
|
||||
doublereal vdp = (pressure() - m_spthermo->refPressure())/
|
||||
molarDensity();
|
||||
doublereal xx;
|
||||
doublereal rt = temperature() * GasConstant;
|
||||
const array_fp& g_RT = gibbs_RT();
|
||||
for (int k = 0; k < m_kk; k++) {
|
||||
xx = fmaxx(SmallNumber, moleFraction(k));
|
||||
mu[k] = rt*(g_RT[k] + log(xx)) + vdp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ConstDensityThermo::getStandardChemPotentials(doublereal* mu0) const {
|
||||
getPureGibbs(mu0);
|
||||
}
|
||||
|
||||
void ConstDensityThermo::initThermo() {
|
||||
m_kk = nSpecies();
|
||||
m_mm = nElements();
|
||||
doublereal tmin = m_spthermo->minTemp();
|
||||
doublereal tmax = m_spthermo->maxTemp();
|
||||
if (tmin > 0.0) m_tmin = tmin;
|
||||
if (tmax > 0.0) m_tmax = tmax;
|
||||
m_p0 = refPressure();
|
||||
|
||||
int leng = m_kk;
|
||||
m_h0_RT.resize(leng);
|
||||
m_g0_RT.resize(leng);
|
||||
m_expg0_RT.resize(leng);
|
||||
m_cp0_R.resize(leng);
|
||||
m_s0_R.resize(leng);
|
||||
m_pe.resize(leng, 0.0);
|
||||
m_pp.resize(leng);
|
||||
}
|
||||
|
||||
|
||||
void ConstDensityThermo::setToEquilState(const doublereal* lambda_RT) {
|
||||
throw CanteraError("setToEquilState","not yet impl.");
|
||||
}
|
||||
|
||||
void ConstDensityThermo::_updateThermo() const {
|
||||
doublereal tnow = temperature();
|
||||
if (m_tlast != tnow) {
|
||||
m_spthermo->update(tnow, &m_cp0_R[0], &m_h0_RT[0],
|
||||
&m_s0_R[0]);
|
||||
m_tlast = tnow;
|
||||
int k;
|
||||
for (k = 0; k < m_kk; k++) {
|
||||
m_g0_RT[k] = m_h0_RT[k] - m_s0_R[k];
|
||||
}
|
||||
m_tlast = tnow;
|
||||
}
|
||||
}
|
||||
|
||||
void ConstDensityThermo::setParametersFromXML(const XML_Node& eosdata) {
|
||||
eosdata._require("model","Incompressible");
|
||||
doublereal rho = getFloat(eosdata, "density", "-");
|
||||
setDensity(rho);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
451
Cantera/src/thermo/ConstDensityThermo.h
Executable file
451
Cantera/src/thermo/ConstDensityThermo.h
Executable file
|
|
@ -0,0 +1,451 @@
|
|||
/**
|
||||
* @file ConstDensityThermo.h
|
||||
* Header for a Thermo manager for incompressible ThermoPhases
|
||||
* (see \ref thermoprops and \link Cantera::ConstDensityThermo ConstDensityThermo\endlink).
|
||||
*/
|
||||
/*
|
||||
* $Author$
|
||||
* $Date$
|
||||
* $Revision$
|
||||
*
|
||||
* Copyright 2002 California Institute of Technology
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CT_CONSTRHOTHERMO_H
|
||||
#define CT_CONSTRHOTHERMO_H
|
||||
|
||||
#include "ct_defs.h"
|
||||
#include "mix_defs.h"
|
||||
#include "ThermoPhase.h"
|
||||
#include "SpeciesThermo.h"
|
||||
#include "utilities.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
//! Overloads the virtual methods of class ThermoPhase to implement the
|
||||
//! incompressible equation of state.
|
||||
/**
|
||||
*
|
||||
*
|
||||
* <b> Specification of Species Standard State Properties </b>
|
||||
*
|
||||
*
|
||||
* <b> Specification of Solution Thermodynamic Properties </b>
|
||||
*
|
||||
* The density is assumed to be constant, no matter what the concentration of the solution.
|
||||
*
|
||||
*
|
||||
* <b> Application within %Kinetics Managers </b>
|
||||
*
|
||||
*
|
||||
* <b> XML Example </b>
|
||||
*
|
||||
* An example of an XML Element named phase setting up a SurfPhase object named diamond_100
|
||||
* is given below.
|
||||
*
|
||||
* @ingroup thermoprops
|
||||
*/
|
||||
class ConstDensityThermo : public ThermoPhase {
|
||||
|
||||
public:
|
||||
|
||||
//! Constructor.
|
||||
/*!
|
||||
*
|
||||
*/
|
||||
ConstDensityThermo() : m_tlast(0.0) {}
|
||||
|
||||
//! Destructor
|
||||
virtual ~ConstDensityThermo() {}
|
||||
|
||||
// overloaded methods of class ThermoPhase
|
||||
|
||||
virtual int eosType() const;
|
||||
|
||||
//! Return the Molar Enthalpy. Units: J/kmol.
|
||||
/*!
|
||||
*
|
||||
*/
|
||||
|
||||
/// Molar enthalpy. Units: J/kmol.
|
||||
virtual doublereal enthalpy_mole() const;
|
||||
|
||||
/// Molar internal energy. Units: J/kmol.
|
||||
virtual doublereal intEnergy_mole() const;
|
||||
|
||||
|
||||
/// Molar entropy. Units: J/kmol/K.
|
||||
virtual doublereal entropy_mole() const;
|
||||
|
||||
/// Molar Gibbs function. Units: J/kmol.
|
||||
virtual doublereal gibbs_mole() const;
|
||||
|
||||
/// Molar heat capacity at constant pressure. Units: J/kmol/K.
|
||||
virtual doublereal cp_mole() const;
|
||||
|
||||
/// Molar heat capacity at constant volume. Units: J/kmol/K.
|
||||
virtual doublereal cv_mole() const;
|
||||
|
||||
//! Return the thermodynamic pressure (Pa).
|
||||
/*!
|
||||
* This method must be overloaded in derived classes. Since the
|
||||
* mass density, temperature, and mass fractions are stored,
|
||||
* this method should use these values to implement the
|
||||
* mechanical equation of state \f$ P(T, \rho, Y_1, \dots,
|
||||
* Y_K) \f$.
|
||||
*/
|
||||
virtual doublereal pressure() const;
|
||||
|
||||
//! Set the internally storred pressure (Pa) at constant
|
||||
//! temperature and composition
|
||||
/*!
|
||||
* This method must be reimplemented in derived classes, where it
|
||||
* may involve the solution of a nonlinear equation. Within %Cantera,
|
||||
* the independent variable is the density. Therefore, this function
|
||||
* solves for the density that will yield the desired input pressure.
|
||||
* The temperature and composition iare held constant during this process.
|
||||
*
|
||||
* This base class function will print an error, if not overwritten.
|
||||
*
|
||||
* @param p input Pressure (Pa)
|
||||
*/
|
||||
virtual void setPressure(doublereal p);
|
||||
|
||||
//! 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. Note that they may
|
||||
* or may not have units of concentration --- they might be
|
||||
* partial pressures, mole fractions, or surface coverages,
|
||||
* for example.
|
||||
*
|
||||
* @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;
|
||||
|
||||
//! Get the array of non-dimensional molar-based activity coefficients at
|
||||
//! the current solution temperature, pressure, and solution concentration.
|
||||
/*!
|
||||
* @param ac Output vector of activity coefficients. Length: m_kk.
|
||||
*/
|
||||
virtual void getActivityCoefficients(doublereal* ac) const;
|
||||
|
||||
//! Get the species chemical potentials. Units: J/kmol.
|
||||
/*!
|
||||
* This function returns a vector of chemical potentials of the
|
||||
* species in solution at the current temperature, pressure
|
||||
* and mole fraction of the solution.
|
||||
*
|
||||
* @param mu Output vector of species chemical
|
||||
* potentials. Length: m_kk. Units: J/kmol
|
||||
*/
|
||||
virtual void getChemPotentials(doublereal* mu) const;
|
||||
|
||||
//! Get the array of chemical potentials at unit activity for the species
|
||||
//! at their standard states at the current <I>T</I> and <I>P</I> of the solution.
|
||||
/*!
|
||||
* 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;
|
||||
|
||||
//! 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. In many cases, this quantity
|
||||
* will be the same for all species in a phase - for example,
|
||||
* for an ideal gas \f$ C^0_k = P/\hat R T \f$. For this
|
||||
* reason, this method returns a single value, instead of an
|
||||
* array. However, for phases in which the standard
|
||||
* concentration is species-specific (e.g. surface species of
|
||||
* different sizes), this method may be called with an
|
||||
* optional parameter indicating the species.
|
||||
*
|
||||
* @param k Optional parameter indicating the species. The default
|
||||
* is to assume this refers to species 0.
|
||||
* @return
|
||||
* Returns the standard Concentration in units of m3 kmol-1.
|
||||
*/
|
||||
virtual doublereal standardConcentration(int 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(int k=0) const;
|
||||
|
||||
//! Get the Gibbs functions for the standard
|
||||
//! state of the species at the current <I>T</I> and <I>P</I> of the solution
|
||||
/*!
|
||||
* Units are Joules/kmol
|
||||
* @param gpure Output vector of standard state gibbs free energies
|
||||
* Length: m_kk.
|
||||
*/
|
||||
virtual void getPureGibbs(doublereal* gpure) const {
|
||||
const array_fp& gibbsrt = gibbs_RT();
|
||||
scale(gibbsrt.begin(), gibbsrt.end(), gpure, _RT());
|
||||
}
|
||||
|
||||
//! Get the nondimensional Enthalpy functions for the species
|
||||
//! at their standard states at the current <I>T</I> and <I>P</I> of the solution.
|
||||
/*!
|
||||
* @param hrt Output vector of nondimensional standard state enthalpies.
|
||||
* Length: m_kk.
|
||||
*/
|
||||
void getEnthalpy_RT(doublereal* hrt) const {
|
||||
const array_fp& _h = enthalpy_RT();
|
||||
std::copy(_h.begin(), _h.end(), hrt);
|
||||
}
|
||||
|
||||
//! Get the array of nondimensional Entropy functions for the
|
||||
//! standard state species at the current <I>T</I> and <I>P</I> of the solution.
|
||||
/*!
|
||||
* @param sr Output vector of nondimensional standard state entropies.
|
||||
* Length: m_kk.
|
||||
*/
|
||||
void getEntropy_R(doublereal* sr) const {
|
||||
const array_fp& _s = entropy_R();
|
||||
std::copy(_s.begin(), _s.end(), sr);
|
||||
}
|
||||
|
||||
//! Get the nondimensional Gibbs functions for the species
|
||||
//! in their standard states at the current <I>T</I> and <I>P</I> of the solution.
|
||||
/*!
|
||||
* @param grt Output vector of nondimensional standard state gibbs free energies
|
||||
* Length: m_kk.
|
||||
*/
|
||||
virtual void getGibbs_RT(doublereal* grt) const {
|
||||
const array_fp& gibbsrt = gibbs_RT();
|
||||
std::copy(gibbsrt.begin(), gibbsrt.end(), grt);
|
||||
}
|
||||
|
||||
//! Get the nondimensional Heat Capacities at constant
|
||||
//! pressure for the species standard states
|
||||
//! at the current <I>T</I> and <I>P</I> of the solution
|
||||
/*!
|
||||
* @param cpr Output vector of nondimensional standard state heat capacities
|
||||
* Length: m_kk.
|
||||
*/
|
||||
void getCp_R(doublereal* cpr) const {
|
||||
const array_fp& _cpr = cp_R();
|
||||
std::copy(_cpr.begin(), _cpr.end(), cpr);
|
||||
}
|
||||
|
||||
|
||||
// new methods defined here
|
||||
|
||||
//! Returns a reference to the vector of nondimensional
|
||||
//! enthalpies of the reference state at the current temperature
|
||||
//! of the solution and the reference pressure for the species.
|
||||
const array_fp& enthalpy_RT() const {
|
||||
_updateThermo();
|
||||
return m_h0_RT;
|
||||
}
|
||||
|
||||
//! Returns a reference to the vector of nondimensional
|
||||
//! Gibbs Free Energies of the reference state at the current temperature
|
||||
//! of the solution and the reference pressure for the species.
|
||||
const array_fp& gibbs_RT() const {
|
||||
_updateThermo();
|
||||
return m_g0_RT;
|
||||
}
|
||||
|
||||
//! Returns a reference to the vector of exponentials of the nondimensional
|
||||
//! Gibbs Free Energies of the reference state at the current temperature
|
||||
//! of the solution and the reference pressure for the species.
|
||||
const array_fp& expGibbs_RT() const {
|
||||
_updateThermo();
|
||||
int k;
|
||||
for (k = 0; k != m_kk; k++) m_expg0_RT[k] = std::exp(m_g0_RT[k]);
|
||||
return m_expg0_RT;
|
||||
}
|
||||
|
||||
//! Returns a reference to the vector of nondimensional
|
||||
//! entropies of the reference state at the current temperature
|
||||
//! of the solution and the reference pressure for each species.
|
||||
const array_fp& entropy_R() const {
|
||||
_updateThermo();
|
||||
return m_s0_R;
|
||||
}
|
||||
|
||||
//! Returns a reference to the vector of nondimensional
|
||||
//! constant pressure heat capacities of the reference state
|
||||
//! at the current temperature of the solution
|
||||
//! and reference pressure for each species.
|
||||
const array_fp& cp_R() const {
|
||||
_updateThermo();
|
||||
return m_cp0_R;
|
||||
}
|
||||
|
||||
//! Set the potential energy of species k
|
||||
/*!
|
||||
* @param k species index
|
||||
* @param pe Potential energy (J kmol-1).
|
||||
*/
|
||||
virtual void setPotentialEnergy(int k, doublereal pe) {
|
||||
m_pe[k] = pe;
|
||||
}
|
||||
|
||||
//! Returns the potential energy of species k
|
||||
/*!
|
||||
* @param k species index
|
||||
*/
|
||||
virtual doublereal potentialEnergy(int k) const {
|
||||
return m_pe[k];
|
||||
}
|
||||
|
||||
//! Initialize the ThermoPhase object after all species have been set up
|
||||
/*!
|
||||
* @internal Initialize.
|
||||
*
|
||||
* This method is provided to allow
|
||||
* subclasses to perform any initialization required after all
|
||||
* species have been added. For example, it might be used to
|
||||
* resize internal work arrays that must have an entry for
|
||||
* each species. The base class implementation does nothing,
|
||||
* and subclasses that do not require initialization do not
|
||||
* need to overload this method. When importing a CTML phase
|
||||
* description, this method is called from ThermoPhase::initThermoXML(),
|
||||
* which is called from importPhase(),
|
||||
* just prior to returning from function importPhase().
|
||||
*
|
||||
* @see importCTML.cpp
|
||||
*/
|
||||
virtual void initThermo();
|
||||
|
||||
//!This method is used by the ChemEquil equilibrium solver.
|
||||
/*!
|
||||
* It sets the state such that the chemical potentials satisfy
|
||||
* \f[ \frac{\mu_k}{\hat R T} = \sum_m A_{k,m}
|
||||
* \left(\frac{\lambda_m} {\hat R T}\right) \f] where
|
||||
* \f$ \lambda_m \f$ is the element potential of element m. The
|
||||
* temperature is unchanged. Any phase (ideal or not) that
|
||||
* implements this method can be equilibrated by ChemEquil.
|
||||
*
|
||||
* @param lambda_RT Input vector of dimensionless element potentials
|
||||
* The length is equal to nElements().
|
||||
*/
|
||||
virtual void setToEquilState(const doublereal* lambda_RT);
|
||||
|
||||
|
||||
//! Set the equation of state parameters
|
||||
/*!
|
||||
* @internal
|
||||
* The number and meaning of these depends on the subclass.
|
||||
*
|
||||
* @param n number of parameters
|
||||
* @param c array of \a n coefficients
|
||||
*/
|
||||
virtual void setParameters(int n, doublereal* c) {
|
||||
setDensity(c[0]);
|
||||
}
|
||||
|
||||
//! Get the equation of state parameters in a vector
|
||||
/*!
|
||||
* @internal
|
||||
* The number and meaning of these depends on the subclass.
|
||||
*
|
||||
* @param n number of parameters
|
||||
* @param c array of \a n coefficients
|
||||
*/
|
||||
virtual void getParameters(int &n, doublereal * const c) {
|
||||
double d = density();
|
||||
c[0] = d;
|
||||
n = 1;
|
||||
}
|
||||
|
||||
//! Set equation of state parameter values from XML entries.
|
||||
/*!
|
||||
*
|
||||
* This method is called by function importPhase() in
|
||||
* file importCTML.cpp when processing a phase definition in
|
||||
* an input file. It should be overloaded in subclasses to set
|
||||
* any parameters that are specific to that particular phase
|
||||
* model. Note, this method is called before the phase is
|
||||
* initialzed with elements and/or species.
|
||||
*
|
||||
* @param eosdata An XML_Node object corresponding to
|
||||
* the "thermo" entry for this phase in the input file.
|
||||
*/
|
||||
virtual void setParametersFromXML(const XML_Node& eosdata);
|
||||
|
||||
protected:
|
||||
|
||||
//! number of elements
|
||||
int m_mm;
|
||||
|
||||
|
||||
//! Minimum temperature for valid species standard state thermo props
|
||||
/*!
|
||||
* This is the minimum temperature at which all species have valid standard
|
||||
* state thermo props defined.
|
||||
*/
|
||||
doublereal m_tmin;
|
||||
|
||||
//! Maximum temperature for valid species standard state thermo props
|
||||
/*!
|
||||
* This is the maximum temperature at which all species have valid standard
|
||||
* state thermo props defined.
|
||||
*/
|
||||
doublereal m_tmax;
|
||||
|
||||
//! Reference state pressure
|
||||
/*!
|
||||
* Value of the reference state pressure in Pascals.
|
||||
* All species must have the same reference state pressure.
|
||||
*/
|
||||
doublereal m_p0;
|
||||
|
||||
//! last value of the temperature processed by reference state
|
||||
mutable doublereal m_tlast;
|
||||
|
||||
//! Temporary storage for dimensionless reference state enthalpies
|
||||
mutable array_fp m_h0_RT;
|
||||
|
||||
//! Temporary storage for dimensionless reference state heat capacities
|
||||
mutable array_fp m_cp0_R;
|
||||
|
||||
//! Temporary storage for dimensionless reference state gibbs energies
|
||||
mutable array_fp m_g0_RT;
|
||||
|
||||
//! Temporary storage for dimensionless reference state entropies
|
||||
mutable array_fp m_s0_R;
|
||||
|
||||
//! currently unsed
|
||||
/*!
|
||||
* @deprecated
|
||||
*/
|
||||
mutable array_fp m_expg0_RT;
|
||||
|
||||
//! Currently unused
|
||||
/*
|
||||
* @deprecated
|
||||
*/
|
||||
mutable array_fp m_pe;
|
||||
|
||||
//! Temporary array containing internally calculated partial pressures
|
||||
mutable array_fp m_pp;
|
||||
|
||||
//! Current pressure (Pa)
|
||||
doublereal m_press;
|
||||
|
||||
private:
|
||||
|
||||
//! Function to update the reference state thermo functions
|
||||
void _updateThermo() const;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
490
Cantera/src/thermo/Constituents.cpp
Executable file
490
Cantera/src/thermo/Constituents.cpp
Executable file
|
|
@ -0,0 +1,490 @@
|
|||
/**
|
||||
* @file Constituents.cpp
|
||||
* Header file Class \link Cantera::Constituents Constitutents\endlink which
|
||||
* manages a set of elements and species (see \ref phases).
|
||||
*/
|
||||
|
||||
/* $Author$
|
||||
* $Date$
|
||||
* $Revision$
|
||||
*
|
||||
|
||||
*/
|
||||
|
||||
// Copyright 2001 California Institute of Technology
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma warning(disable:4786)
|
||||
#endif
|
||||
|
||||
#include "Constituents.h"
|
||||
#include "Elements.h"
|
||||
using namespace std;
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
/*
|
||||
* Constructor sets all base variable types to zero. Also, it
|
||||
* sets the pointer to the Elements object for this object to the
|
||||
* default value of BaseElements. If the BaseElements Elements
|
||||
* object doesn't exist, it creates it.
|
||||
*
|
||||
* Input
|
||||
* --------
|
||||
* ptr_Elements: If the Constituents object requires a different
|
||||
* Elements object than the default one, input
|
||||
* address here. This argument defaults to null,
|
||||
* in which case the default Elements Object is
|
||||
* chosen.
|
||||
*/
|
||||
|
||||
/*
|
||||
* DGG: I have reversed the role of ptr_Elements. In this version,
|
||||
* the default is that a new Elements object is created, so this
|
||||
* Constituents object is independent of any other object. But if
|
||||
* ptr_Elements is supplied, it will be used. This way, a class
|
||||
* implementing a multi-phase mixture is responsible for
|
||||
* maintaining the global elements list for the mixture, and no
|
||||
* static global element list is required.
|
||||
*/
|
||||
Constituents::Constituents(Elements* ptr_Elements) :
|
||||
m_kk(0),
|
||||
m_speciesFrozen(false) ,
|
||||
m_Elements(ptr_Elements) {
|
||||
|
||||
if (!m_Elements) m_Elements = new Elements();
|
||||
|
||||
// Register subscription to Elements object whether or not we
|
||||
// created it here.
|
||||
m_Elements->subscribe();
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor for class Constituents.
|
||||
*
|
||||
* Some cleanup of of the Global_Elements_List array is
|
||||
* effected by unsubscribing to m_Elements.
|
||||
*/
|
||||
Constituents::~Constituents()
|
||||
{
|
||||
int ileft = m_Elements->unsubscribe();
|
||||
/*
|
||||
* Here we may delete Elements Objects or not. Right now, we
|
||||
* will delete them. We also delete the global pointer entry
|
||||
* to keep everything consistent.
|
||||
*/
|
||||
if (ileft <= 0) {
|
||||
vector<Elements *>::iterator it;
|
||||
for (it = Elements::Global_Elements_List.begin();
|
||||
it != Elements::Global_Elements_List.end(); ++it) {
|
||||
if (*it == m_Elements) {
|
||||
Elements::Global_Elements_List.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete m_Elements;
|
||||
}
|
||||
}
|
||||
|
||||
int Constituents::nElements() const { return m_Elements->nElements(); }
|
||||
|
||||
|
||||
/**
|
||||
* Return the Atomic weight of element m.
|
||||
* units = Kg / Kmol
|
||||
*/
|
||||
doublereal Constituents::atomicWeight(int m) const {
|
||||
return m_Elements->atomicWeight(m);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a reference to the vector of atomic weights pertinent
|
||||
* to this constituents object
|
||||
* units = kg / Kmol
|
||||
*/
|
||||
const vector_fp& Constituents::atomicWeights() const {
|
||||
return m_Elements->atomicWeights();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the atomic number of element m.
|
||||
*/
|
||||
int Constituents::atomicNumber(int m) const {
|
||||
return m_Elements->atomicNumber(m);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add an element to the set.
|
||||
* @param symbol symbol string
|
||||
* @param weight atomic weight in kg/mol.
|
||||
*
|
||||
* If weight is not given, then a lookup is performed in the
|
||||
* element object
|
||||
*
|
||||
*/
|
||||
void Constituents::
|
||||
addElement(const std::string& symbol, doublereal weight)
|
||||
{
|
||||
m_Elements->addElement(symbol, weight);
|
||||
}
|
||||
|
||||
void Constituents::
|
||||
addElement(const XML_Node& e)
|
||||
{
|
||||
m_Elements->addElement(e);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a unique element to the set. A check on the symbol is made
|
||||
* If the symbol is already an element, then a new element is
|
||||
* not created.
|
||||
*
|
||||
* @param symbol symbol string
|
||||
* @param weight atomic weight in kg/mol.
|
||||
*
|
||||
* If weight is not given, then a lookup is performed in the
|
||||
* element object
|
||||
*
|
||||
* -> Passthrough to the Element lvl.
|
||||
*/
|
||||
void Constituents::
|
||||
addUniqueElement(const std::string& symbol, doublereal weight)
|
||||
{
|
||||
m_Elements->addUniqueElement(symbol, weight);
|
||||
}
|
||||
|
||||
void Constituents::
|
||||
addUniqueElement(const XML_Node& e)
|
||||
{
|
||||
m_Elements->addUniqueElement(e);
|
||||
}
|
||||
|
||||
void Constituents::addElementsFromXML(const XML_Node& phase) {
|
||||
m_Elements->addElementsFromXML(phase);
|
||||
}
|
||||
|
||||
/*
|
||||
* -> Passthrough to the Element lvl.
|
||||
*/
|
||||
void Constituents::freezeElements() {
|
||||
m_Elements->freezeElements();
|
||||
}
|
||||
|
||||
/*
|
||||
* -> Passthrough to the Element lvl.
|
||||
*/
|
||||
bool Constituents::elementsFrozen() {
|
||||
return m_Elements->elementsFrozen();
|
||||
}
|
||||
|
||||
/*
|
||||
* Index of element named \a name. The index is an integer
|
||||
* assigned to each element in the order it was added,
|
||||
* beginning with 0 for the first element. If \a name is not
|
||||
* the name of an element in the set, then the value -1 is
|
||||
* returned.
|
||||
*
|
||||
*
|
||||
* -> Passthrough to the Element class.
|
||||
*/
|
||||
int Constituents::elementIndex(std::string name) const {
|
||||
return (m_Elements->elementIndex(name));
|
||||
}
|
||||
|
||||
/*
|
||||
* Name of the element with index m.
|
||||
*
|
||||
* This is a passthrough routine to the Element object.
|
||||
* @param m @{ Element index. @}
|
||||
* \exception If m < 0 or m >= nElements(), the
|
||||
* exception, ElementRangeError, is thrown.
|
||||
*/
|
||||
string Constituents::elementName(int m) const {
|
||||
return (m_Elements->elementName(m));
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* elementNames():
|
||||
*
|
||||
* Returns a read-only reference to the vector of element names.
|
||||
* @code
|
||||
* Constituents c;
|
||||
* ...
|
||||
* const vector<string>& enames = c.elementNames();
|
||||
* int n = enames.size();
|
||||
* for (int i = 0; i < n; i++) cout << enames[i] << endl;
|
||||
* @endcode
|
||||
*
|
||||
*
|
||||
* -> Passthrough to the Element lvl.
|
||||
*/
|
||||
const vector<string>& Constituents::elementNames() const {
|
||||
return m_Elements->elementNames();
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* molecularWeight()
|
||||
*
|
||||
* Returns the molecular weight of a species given the species index
|
||||
*
|
||||
* units = kg / kmol.
|
||||
*/
|
||||
doublereal Constituents::molecularWeight(int k) const {
|
||||
if (k < 0 || k >= nSpecies()) {
|
||||
throw SpeciesRangeError("Constituents::molecularWeight",
|
||||
k, nSpecies());
|
||||
}
|
||||
return m_weight[k];
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* molecularWeights()
|
||||
*
|
||||
* Returns a const reference to the vector of molecular weights
|
||||
* for all of the species defined in the object.
|
||||
*
|
||||
* units = kg / kmol.
|
||||
*/
|
||||
const array_fp& Constituents::molecularWeights() const {
|
||||
return m_weight;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* charge():
|
||||
*
|
||||
* Electrical charge of one species k molecule, divided by
|
||||
* \f$ e = 1.602 \times 10^{-19}\f$ Coulombs.
|
||||
*/
|
||||
doublereal Constituents::charge(int k) const {
|
||||
return m_speciesCharge[k];
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* addSpecies()
|
||||
*
|
||||
* Add a species to a Constituents object. Note, no check is made
|
||||
* as to whether the species has a unique name.
|
||||
*
|
||||
* Input
|
||||
* ---------
|
||||
* name = string containing the name
|
||||
* comp[]
|
||||
* charge =
|
||||
* weight = weight of the species. Default = 0.0.
|
||||
* Note, the weight is a bit redundent and potentially
|
||||
* harmful. If weight is less than or equal to zero,
|
||||
* the weight is calculated from the element composition
|
||||
* and it need not be supplied on the command line.
|
||||
*/
|
||||
void Constituents::
|
||||
addSpecies(const std::string& name, const doublereal* comp,
|
||||
doublereal charge, doublereal size) {
|
||||
m_Elements->freezeElements();
|
||||
m_speciesNames.push_back(name);
|
||||
m_speciesCharge.push_back(charge);
|
||||
m_speciesSize.push_back(size);
|
||||
double wt = 0.0;
|
||||
int m_mm = m_Elements->nElements();
|
||||
const vector_fp &aw = m_Elements->atomicWeights();
|
||||
for (int m = 0; m < m_mm; m++) {
|
||||
m_speciesComp.push_back(comp[m]);
|
||||
wt += comp[m] * aw[m];
|
||||
}
|
||||
m_weight.push_back(wt);
|
||||
m_kk++;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* addUniqueSpecies():
|
||||
*
|
||||
* Add a species to a Constituents object. This routine will
|
||||
* first check to see if the species is already part of the
|
||||
* phase. It does this via a string comparison with the
|
||||
* existing species in the phase.
|
||||
*/
|
||||
void Constituents::
|
||||
addUniqueSpecies(const std::string& name, const doublereal* comp,
|
||||
doublereal charge, doublereal size) {
|
||||
vector<string>::const_iterator it = m_speciesNames.begin();
|
||||
for (int k = 0; k < m_kk; k++) {
|
||||
if (*it == name) {
|
||||
/*
|
||||
* We have found a match. At this point we could do some
|
||||
* compatibility checks. However, let's just return for the
|
||||
* moment without specifying any error.
|
||||
*/
|
||||
int m_mm = m_Elements->nElements();
|
||||
for (int i = 0; i < m_mm; i++) {
|
||||
if (comp[i] != m_speciesComp[m_kk * m_mm + i]) {
|
||||
throw CanteraError("addUniqueSpecies",
|
||||
"Duplicate species have different "
|
||||
"compositions: " + *it);
|
||||
}
|
||||
}
|
||||
if (charge != m_speciesCharge[m_kk]) {
|
||||
throw CanteraError("addUniqueSpecies",
|
||||
"Duplicate species have different "
|
||||
"charges: " + *it);
|
||||
}
|
||||
if (size != m_speciesSize[m_kk]) {
|
||||
throw CanteraError("addUniqueSpecies",
|
||||
"Duplicate species have different "
|
||||
"sizes: " + *it);
|
||||
}
|
||||
return;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
addSpecies(name, comp, charge, size);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* freezeSpecies()
|
||||
* Set the boolean indicating that we are no longer allowing
|
||||
* species to be added to the Constituents class object.
|
||||
*/
|
||||
void Constituents::freezeSpecies() {
|
||||
m_speciesFrozen = true;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* speciesIndex()
|
||||
*
|
||||
* Index of species named \c name. The first species added
|
||||
* will have index 0, and the last one index nSpecies() - 1.
|
||||
*
|
||||
* Note, the [] operator shouldn't be used for map's because it
|
||||
* creates new entries. Here, we use find() to look up entries.
|
||||
*
|
||||
* If name isn't in the list, then a -1 is returned.
|
||||
*/
|
||||
int Constituents::speciesIndex(std::string name) const {
|
||||
vector<string>::const_iterator it = m_speciesNames.begin();
|
||||
for (int k = 0; k < m_kk; k++) {
|
||||
if (*it == name) {
|
||||
/*
|
||||
* We have found a match.
|
||||
*/
|
||||
return k;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* speciesName()
|
||||
*
|
||||
* Name of the species with index k
|
||||
*/
|
||||
string Constituents::speciesName(int k) const {
|
||||
if (k < 0 || k >= nSpecies())
|
||||
throw SpeciesRangeError("Constituents::speciesName",
|
||||
k, nSpecies());
|
||||
return m_speciesNames[k];
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* speciesNames()
|
||||
*
|
||||
* Return a const reference to the vector of species names
|
||||
*/
|
||||
const vector<string>& Constituents::speciesNames() const {
|
||||
return m_speciesNames;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* ready():
|
||||
* True if both elements and species have been frozen
|
||||
*/
|
||||
bool Constituents::ready() const {
|
||||
return (m_Elements->elementsFrozen() && m_speciesFrozen);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the number of atoms of element \c m in species \c k.
|
||||
*/
|
||||
doublereal Constituents::nAtoms(int k, int m) const
|
||||
{
|
||||
const int m_mm = m_Elements->nElements();
|
||||
if (m < 0 || m >=m_mm)
|
||||
throw ElementRangeError("Constituents::nAtoms",m,nElements());
|
||||
if (k < 0 || k >= nSpecies())
|
||||
throw SpeciesRangeError("Constituents::nAtoms",k,nSpecies());
|
||||
return m_speciesComp[m_mm * k + m];
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* getAtoms()
|
||||
*
|
||||
* Get a vector containing the atomic composition
|
||||
* of species k
|
||||
*/
|
||||
void Constituents::getAtoms(int k, double *atomArray) const
|
||||
{
|
||||
const int m_mm = m_Elements->nElements();
|
||||
for (int m = 0; m < m_mm; m++) {
|
||||
atomArray[m] = (double) m_speciesComp[m_mm * k + m];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This copy constructor just calls the assignment operator
|
||||
* for this class.
|
||||
* The assignment operator does a deep copy.
|
||||
*/
|
||||
Constituents::Constituents(const Constituents& right) {
|
||||
*this = right;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assignment operator for the Constituents class.
|
||||
* Right now we pretty much do a straight uncomplicated
|
||||
* copy of all of the protected data.
|
||||
*/
|
||||
Constituents& Constituents::operator=(const Constituents& right) {
|
||||
/*
|
||||
* Check for self assignment.
|
||||
*/
|
||||
if (this == &right) return *this;
|
||||
/*
|
||||
* We do a straight assignment operator on all of the
|
||||
* data. The vectors are copied.
|
||||
*/
|
||||
m_kk = right.m_kk;
|
||||
m_weight = right.m_weight;
|
||||
m_speciesFrozen = right.m_speciesFrozen;
|
||||
if (m_Elements) {
|
||||
m_Elements->unsubscribe();
|
||||
}
|
||||
m_Elements = right.m_Elements;
|
||||
if (m_Elements) {
|
||||
m_Elements->subscribe();
|
||||
}
|
||||
m_speciesNames = right.m_speciesNames;
|
||||
m_speciesComp = right.m_speciesComp;
|
||||
m_speciesCharge = right.m_speciesCharge;
|
||||
m_speciesSize = right.m_speciesSize;
|
||||
/*
|
||||
* Return the reference to the current object
|
||||
*/
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
392
Cantera/src/thermo/Constituents.h
Executable file
392
Cantera/src/thermo/Constituents.h
Executable file
|
|
@ -0,0 +1,392 @@
|
|||
/**
|
||||
* @file Constituents.h
|
||||
* Header file Class \link Cantera::Constituents Constitutents\endlink which
|
||||
* manages a set of elements and species (see \ref phases).
|
||||
*/
|
||||
|
||||
/* $Author$
|
||||
* $Date$
|
||||
* $Revision$
|
||||
*
|
||||
*/
|
||||
|
||||
// Copyright 2001 California Institute of Technology
|
||||
|
||||
|
||||
#ifndef CT_CONSTIT_H
|
||||
#define CT_CONSTIT_H
|
||||
|
||||
|
||||
#include "ct_defs.h"
|
||||
//using namespace std;
|
||||
|
||||
#include "SpeciesThermo.h"
|
||||
#include "ctexceptions.h"
|
||||
#include "stringUtils.h"
|
||||
#include "xml.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
class Elements;
|
||||
|
||||
/************** DEFINITIONS OF ERRORS *****************************/
|
||||
|
||||
//! Specific fatal error indicating that the index of a species is out of range.
|
||||
/*!
|
||||
*
|
||||
* @ingroup errorhandling
|
||||
*/
|
||||
class SpeciesRangeError : public CanteraError {
|
||||
public:
|
||||
//! Constructor
|
||||
/*!
|
||||
* @param func Function where the error occurred.
|
||||
* @param k current species index value
|
||||
* @param kmax Maximum permissible species index value. The
|
||||
* minimum permissible species index value is assumed to be 0
|
||||
*
|
||||
*/
|
||||
SpeciesRangeError(std::string func, int k, int kmax) :
|
||||
CanteraError(func, "Species index " + int2str(k) +
|
||||
" outside valid range of 0 to " + int2str(kmax-1)) {}
|
||||
};
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
|
||||
//! Class %Constituents manages a set of elements and species.
|
||||
/*!
|
||||
* Class %Constituents is designed to provide information
|
||||
* about the elements and species in a phase - names, index
|
||||
* numbers (location in arrays), atomic or molecular weights,
|
||||
* etc. No computations are performed by the methods of this
|
||||
* class. The set of elements must include all those that compose
|
||||
* the species, but may include additional elements. The species
|
||||
* all must belong to the same phase.
|
||||
*
|
||||
* @ingroup phases
|
||||
*/
|
||||
class Constituents {
|
||||
|
||||
public:
|
||||
|
||||
//! Constructor.
|
||||
/*!
|
||||
* Constructor sets all base variable types to zero. Also, it
|
||||
* sets the pointer to the Elements object for this object.
|
||||
*
|
||||
* @param ptr_Elements
|
||||
* The default is that a new Elements object is created, so this
|
||||
* Constituents object is independent of any other object. But if
|
||||
* ptr_Elements is supplied, it will be used. This way, a class
|
||||
* implementing a multi-phase mixture is responsible for
|
||||
* maintaining the global elements list for the mixture, and no
|
||||
* static global element list is required.
|
||||
*/
|
||||
Constituents(Elements* ptr_Elements = 0);
|
||||
|
||||
/// Destructor.
|
||||
~Constituents();
|
||||
|
||||
/// This copy constructor just calls the assignment operator
|
||||
/// for this class.
|
||||
/*!
|
||||
* @param right reference to the object to be copied.
|
||||
*/
|
||||
Constituents(const Constituents& right);
|
||||
|
||||
/// Assignment operator
|
||||
/*!
|
||||
* @param right Reference to the object to be copied.
|
||||
*/
|
||||
Constituents& operator=(const Constituents& right);
|
||||
|
||||
/// @name Element Information
|
||||
// @{
|
||||
|
||||
/// Name of the element with index m.
|
||||
/// This is a passthrough routine to the Element object.
|
||||
/// \param m Element index.
|
||||
/// \exception If m < 0 or m >= nElements(), the
|
||||
/// exception, ElementRangeError, is thrown.
|
||||
std::string elementName(int m) const;
|
||||
|
||||
|
||||
/// Index of element named 'name'.
|
||||
/// The index is an integer
|
||||
/// assigned to each element in the order it was added,
|
||||
/// beginning with 0 for the first element.
|
||||
/// @param name name of the element
|
||||
///
|
||||
/// If 'name' is not
|
||||
/// the name of an element in the set, then the value -1 is
|
||||
/// returned.
|
||||
int elementIndex(std::string name) const;
|
||||
|
||||
|
||||
/// Atomic weight of element m.
|
||||
/*!
|
||||
* @param m Element index
|
||||
*/
|
||||
doublereal atomicWeight(int m) const;
|
||||
|
||||
/// Atomic number of element m.
|
||||
/*!
|
||||
* @param m Element index
|
||||
*/
|
||||
int atomicNumber(int m) const;
|
||||
|
||||
/// Return a read-only reference to the vector of element names.
|
||||
const std::vector<std::string>& elementNames() const;
|
||||
|
||||
/// Return a read-only reference to the vector of atomic weights.
|
||||
const vector_fp& atomicWeights() const;
|
||||
|
||||
|
||||
/// Number of elements.
|
||||
int nElements() const;
|
||||
|
||||
// @}
|
||||
|
||||
|
||||
|
||||
/// @name Adding Elements and Species
|
||||
/// These methods are used to add new elements or species.
|
||||
/// These are not usually called by user programs.
|
||||
///
|
||||
/// Since species are checked to insure that they are only
|
||||
/// composed of declared elements, it is necessary to first
|
||||
/// add all elements before adding any species.
|
||||
|
||||
//@{
|
||||
|
||||
//! Add an element.
|
||||
/*!
|
||||
* @param symbol Atomic symbol std::string.
|
||||
* @param weight Atomic mass in amu.
|
||||
*/
|
||||
void addElement(const std::string& symbol, doublereal weight);
|
||||
|
||||
//! Add an element from an XML specification.
|
||||
/*!
|
||||
* @param e Reference to the XML_Node where the element is described.
|
||||
*/
|
||||
void addElement(const XML_Node& e);
|
||||
|
||||
//! Adde an element, checking for uniqueness
|
||||
/*!
|
||||
* The uniqueness is checked by comparing the string symbol. If
|
||||
* not unique, nothing is done.
|
||||
*
|
||||
* @param symbol String symbol of the element
|
||||
* @param weight Atomic weight of the element (kg kmol-1).
|
||||
*/
|
||||
void addUniqueElement(const std::string& symbol, doublereal weight);
|
||||
|
||||
//! Adde an element, checking for uniqueness
|
||||
/*!
|
||||
* The uniqueness is checked by comparing the string symbol. If
|
||||
* not unique, nothing is done.
|
||||
*
|
||||
* @param e Reference to the XML_Node where the element is described.
|
||||
*/
|
||||
void addUniqueElement(const XML_Node& e);
|
||||
|
||||
//! Add all elements referenced in an XML_Node tree
|
||||
/*!
|
||||
* @param phase Reference to the top XML_Node of a phase
|
||||
*/
|
||||
void addElementsFromXML(const XML_Node& phase);
|
||||
|
||||
/// Prohibit addition of more elements, and prepare to add species.
|
||||
void freezeElements();
|
||||
|
||||
/// True if freezeElements has been called.
|
||||
bool elementsFrozen();
|
||||
|
||||
//@}
|
||||
|
||||
/// Returns the number of species in the phase
|
||||
int nSpecies() const { return m_kk; }
|
||||
|
||||
//! Molecular weight of species \c k.
|
||||
/*!
|
||||
* @param k index of species \c k
|
||||
* @return
|
||||
* Returns the molecular weight of species \c k.
|
||||
*/
|
||||
doublereal molecularWeight(int k) const;
|
||||
|
||||
//! Return the Molar mass of species \c k
|
||||
/*!
|
||||
* Preferred name for molecular weight.
|
||||
*
|
||||
* @param k index for species
|
||||
* @return
|
||||
* Return the molar mass of species k kg/kmol.
|
||||
*/
|
||||
doublereal molarMass(int k) const {
|
||||
return molecularWeight(k);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a const reference to the vector of molecular weights
|
||||
* of the species
|
||||
*/
|
||||
const vector_fp& molecularWeights() const;
|
||||
|
||||
/*!
|
||||
* Electrical charge of one species k molecule, divided by
|
||||
* the magnitude of the electron charge ( \f$ e = 1.602
|
||||
* \times 10^{-19}\f$ Coulombs). Dimensionless.
|
||||
*
|
||||
* @param k species index
|
||||
*/
|
||||
doublereal charge(int k) const;
|
||||
|
||||
/**
|
||||
* @name Adding Species
|
||||
* These methods are used to add new species.
|
||||
* They are not usually called by user programs.
|
||||
*/
|
||||
//@{
|
||||
void addSpecies(const std::string& name, const doublereal* comp,
|
||||
doublereal charge = 0.0, doublereal size = 1.0);
|
||||
|
||||
//! Add a species to the phase, checking for uniqueness of the name
|
||||
/*!
|
||||
* This routine checks for uniqueness of the string name. It only
|
||||
* adds the species if it is unique.
|
||||
*
|
||||
* @param name String name of the species
|
||||
* @param comp Double vector containing the elemental composition of the
|
||||
* species.
|
||||
* @param charge Charge of the species. Defaults to zero.
|
||||
* @param size Size of the species (meters). Defaults to 1 meter.
|
||||
*/
|
||||
void addUniqueSpecies(const std::string& name, const doublereal* comp,
|
||||
doublereal charge = 0.0,
|
||||
doublereal size = 1.0);
|
||||
|
||||
//! Index of species named 'name'
|
||||
/*!
|
||||
* The first species added
|
||||
* will have index 0, and the last one index nSpecies() - 1.
|
||||
*
|
||||
* @param name String name of the species
|
||||
* @return
|
||||
* Returns the index of the species.
|
||||
*/
|
||||
int speciesIndex(std::string name) const;
|
||||
|
||||
//! Name of the species with index k
|
||||
/*!
|
||||
* @param k index of the species
|
||||
*/
|
||||
std::string speciesName(int k) const;
|
||||
|
||||
/// Return a const referernce to the vector of species names
|
||||
const std::vector<std::string>& speciesNames() const;
|
||||
|
||||
//! This routine returns the size of species k
|
||||
/*!
|
||||
* @param k index of the species
|
||||
* @return
|
||||
* Returns the size of the species. Units are meters.
|
||||
*/
|
||||
doublereal size(int k) const { return m_speciesSize[k]; }
|
||||
|
||||
/**
|
||||
* Prohibit addition of more species, and prepare for
|
||||
* calculations with this set of elements and species.
|
||||
*/
|
||||
void freezeSpecies();
|
||||
|
||||
/// True if freezeSpecies has been called.
|
||||
bool speciesFrozen() { return m_speciesFrozen; }
|
||||
|
||||
/// Remove all elements and species
|
||||
void clear();
|
||||
|
||||
//@}
|
||||
|
||||
/// True if both elements and species have been frozen
|
||||
bool ready() const;
|
||||
|
||||
//! Number of atoms of element \c m in species \c k.
|
||||
/*!
|
||||
* @param k species index
|
||||
* @param m element index
|
||||
*/
|
||||
doublereal nAtoms(int k, int m) const;
|
||||
|
||||
|
||||
//! Get a vector containing the atomic composition of species k
|
||||
/*!
|
||||
* @param k species index
|
||||
* @param atomArray vector containing the atomic number in the species.
|
||||
* Length: m_mm
|
||||
*/
|
||||
void getAtoms(int k, double *atomArray) const;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
//! Number of species in the phase.
|
||||
int m_kk;
|
||||
//! Vector of molecular weights of the species
|
||||
/*!
|
||||
* This vector has length m_kk.
|
||||
* The units of the vector are kg kmol-1.
|
||||
*/
|
||||
vector_fp m_weight;
|
||||
|
||||
//! Boolean indicating whether the number of species has been frozen.
|
||||
/*!
|
||||
* During the construction of the phase, this is false. After
|
||||
* construction of the the phase, this is true.
|
||||
*/
|
||||
bool m_speciesFrozen;
|
||||
|
||||
/*!
|
||||
* Pointer to the element object corresponding to this
|
||||
* phase. Normally, this will be the default Element object
|
||||
* common to all phases.
|
||||
*/
|
||||
Elements * m_Elements;
|
||||
|
||||
//! Vector of the species names
|
||||
std::vector<std::string> m_speciesNames;
|
||||
|
||||
//! Atomic composition of the species.
|
||||
/*!
|
||||
* the number of atoms of i in species k is equal to
|
||||
* m_speciesComp[k * m_mm + i]
|
||||
* The length of this vector is equal to m_kk * m_mm
|
||||
*/
|
||||
vector_fp m_speciesComp;
|
||||
|
||||
/**
|
||||
* m_speciesCharge: Vector of species charges
|
||||
* length = m_kk
|
||||
*/
|
||||
vector_fp m_speciesCharge;
|
||||
|
||||
/**
|
||||
* m_speciesSize(): Vector of species sizes.
|
||||
* length m_kk
|
||||
* This is used in some equations of state
|
||||
* which employ the constant partial molar
|
||||
* volume approximation. It's so fundamental
|
||||
* we've put it at the Constituents class level
|
||||
*/
|
||||
vector_fp m_speciesSize;
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
68
Cantera/src/thermo/Crystal.h
Normal file
68
Cantera/src/thermo/Crystal.h
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/**
|
||||
* @file Crystal.h
|
||||
*
|
||||
* $Author$
|
||||
* $Date$
|
||||
* $Revision$
|
||||
*/
|
||||
#ifndef CT_CRYSTAL_H
|
||||
#define CT_CRYSTAL_H
|
||||
|
||||
#include "MultiPhase.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
/// A class for crystals. Each crystal consists of one or more
|
||||
/// sublattices, each represented by an object of type
|
||||
/// LatticePhase.
|
||||
|
||||
class Crystal : public MultiPhase {
|
||||
|
||||
public:
|
||||
typedef LatticePhase lattice_t;
|
||||
typedef vector<LatticePhase*> lattice_list;
|
||||
|
||||
/// Constructor. The constructor takes no arguments, since
|
||||
/// phases are added using method addPhase.
|
||||
Crystal() : MultiPhase() {}
|
||||
|
||||
/// Destructor. Does nothing. Class MultiPhase does not take
|
||||
/// "ownership" (i.e. responsibility for destroying) the
|
||||
/// phase objects.
|
||||
virtual ~Crystal() {}
|
||||
|
||||
void addLattices(lattice_list& lattices,
|
||||
const vector_fp& latticeSiteDensity);
|
||||
|
||||
/// Add a phase to the mixture.
|
||||
/// @param p pointer to the phase object
|
||||
/// @param moles total number of moles of all species in this phase
|
||||
void addLattice(lattice_t* lattice, doublereal siteDensity) {
|
||||
MultiPhase::addPhase(lattice, siteDensity);
|
||||
}
|
||||
|
||||
/// Return a reference to phase n. The state of phase n is
|
||||
/// also updated to match the state stored locally in the
|
||||
/// mixture object.
|
||||
lattice_t& lattice(index_t n) {
|
||||
return *(lattice_t*)&phase(n);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& s, Cantera::Crystal& x) {
|
||||
size_t ip;
|
||||
for (ip = 0; ip < x.nPhases(); ip++) {
|
||||
s << "*************** Lattice " << ip << " *****************" << endl;
|
||||
s << "SiteDensity: " << x.phaseMoles(ip) << endl;
|
||||
|
||||
s << report(x.phase(ip)) << endl;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -21,7 +21,8 @@
|
|||
#endif
|
||||
|
||||
#include "DebyeHuckel.h"
|
||||
#include "importCTML.h"
|
||||
//#include "importCTML.h"
|
||||
#include "ThermoFactory.h"
|
||||
#include "WaterProps.h"
|
||||
#include "WaterPDSS.h"
|
||||
#include <string.h>
|
||||
|
|
|
|||
83
Cantera/src/thermo/EdgePhase.h
Normal file
83
Cantera/src/thermo/EdgePhase.h
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/**
|
||||
* @file EdgePhase.h
|
||||
* Declarations for the EdgePhase ThermoPhase object, which models the interface
|
||||
* between two surfaces (see \ref thermoprops and \link Cantera::EdgePhase EdgePhase\endlink).
|
||||
*/
|
||||
|
||||
/* $Author$
|
||||
* $Date$
|
||||
* $Revision$
|
||||
*
|
||||
* Copyright 2002 California Institute of Technology
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CT_EDGEPHASE_H
|
||||
#define CT_EDGEPHASE_H
|
||||
|
||||
#include "mix_defs.h"
|
||||
#include "ThermoPhase.h"
|
||||
#include "SurfPhase.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
//! A thermodynamic %Phase representing a one dimensional edge between two surfaces
|
||||
/*!
|
||||
* This thermodynamic function is largely a wrapper around the SurfPhase
|
||||
* thermodynamic object.
|
||||
*
|
||||
* All of the equations and formulations carry through from SurfPhase to this
|
||||
* EdgePhase object.
|
||||
* It should be noted however, that dimensional object with length dimensions,
|
||||
* have their dimensions reduced by one.
|
||||
*
|
||||
* @ingroup thermoprops
|
||||
*/
|
||||
class EdgePhase : public SurfPhase {
|
||||
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
/*!
|
||||
* @param n0 Surface site density (kmol m-1).
|
||||
*/
|
||||
EdgePhase(doublereal n0 = 0.0);
|
||||
|
||||
//! Destructor
|
||||
virtual ~EdgePhase() {}
|
||||
|
||||
//! returns the equation of state type
|
||||
virtual int eosType() const { return cEdge; }
|
||||
|
||||
|
||||
//! Set the Equation-of-State parameters by reading an XML Node Input
|
||||
/*!
|
||||
*
|
||||
* The Equation-of-State data consists of one item, the site density.
|
||||
*
|
||||
* @param thermoData Reference to an XML_Node named thermo
|
||||
* containing the equation-of-state data. The
|
||||
* XML_Node is within the phase XML_Node describing
|
||||
* the %EdgePhase object.
|
||||
*
|
||||
* An example of the contents of the thermoData XML_Node is provided
|
||||
* below. The units attribute is used to supply the units of the
|
||||
* site density in any convenient form. Internally it is changed
|
||||
* into MKS form.
|
||||
*
|
||||
* @code
|
||||
* <thermo model="Edge">
|
||||
* <site_density units="mol/cm"> 3e-15 </site_density>
|
||||
* </thermo>
|
||||
* @endcode
|
||||
*/
|
||||
virtual void setParametersFromXML(const XML_Node& thermoData);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
601
Cantera/src/thermo/Elements.cpp
Normal file
601
Cantera/src/thermo/Elements.cpp
Normal file
|
|
@ -0,0 +1,601 @@
|
|||
/**
|
||||
* @file Elements.cpp
|
||||
* Declaration file for class, Elements, which contains the elements that
|
||||
* make up species (see \ref phases and \link Cantera::Elements Elements\endlink).
|
||||
*
|
||||
* This file contains the definitions for functions in the class Elements.
|
||||
* It also contains a database of atomic weights.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* $RCSfile$
|
||||
* $Author$
|
||||
* $Date$
|
||||
* $Revision$
|
||||
*
|
||||
*
|
||||
****************************************************************************/
|
||||
// Copyright 2003 California Institute of Technology
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma warning(disable:4786)
|
||||
#endif
|
||||
|
||||
#include "Elements.h"
|
||||
#include "xml.h"
|
||||
#include "ctml.h"
|
||||
#include "ctexceptions.h"
|
||||
|
||||
using namespace ctml;
|
||||
using namespace std;
|
||||
|
||||
#ifdef USE_DGG_CODE
|
||||
#include <map>
|
||||
#endif
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
|
||||
/* awData structure */
|
||||
/**
|
||||
* Database for atomic molecular weights
|
||||
*
|
||||
* Values are taken from the 1989 Standard Atomic Weights, CRC
|
||||
*
|
||||
* awTable[] is a static function with scope limited to this file.
|
||||
* It can only be referenced via the static Elements class function,
|
||||
* LookupWtElements().
|
||||
*
|
||||
* units = kg / kg-mol (or equivalently gm / gm-mol)
|
||||
*
|
||||
* (note: this structure was picked because it's simple, compact,
|
||||
* and extensible).
|
||||
*
|
||||
*/
|
||||
struct awData {
|
||||
char name[4]; ///< Null Terminated name, First letter capitalized
|
||||
double atomicWeight; ///< atomic weight in kg / kg-mol
|
||||
};
|
||||
|
||||
/*!
|
||||
* @var static struct awData aWTable[]
|
||||
* \brief aWTable is a vector containing the atomic weights database.
|
||||
*
|
||||
* The size of the table is given by the initial instantiation.
|
||||
*/
|
||||
static struct awData aWTable[] = {
|
||||
{"H", 1.00794},
|
||||
{"D", 2.0 },
|
||||
{"Tr", 3.0 },
|
||||
{"He", 4.002602},
|
||||
{"Li", 6.941 },
|
||||
{"Be", 9.012182},
|
||||
{"B", 10.811 },
|
||||
{"C", 12.011 },
|
||||
{"N", 14.00674},
|
||||
{"O", 15.9994 },
|
||||
{"F", 18.9984032},
|
||||
{"Ne", 20.1797 },
|
||||
{"Na", 22.98977},
|
||||
{"Mg", 24.3050 },
|
||||
{"Al", 26.98154},
|
||||
{"Si", 28.0855 },
|
||||
{"P", 30.97376},
|
||||
{"S", 32.066 },
|
||||
{"Cl", 35.4527 },
|
||||
{"Ar", 39.948 },
|
||||
{"K", 39.0983 },
|
||||
{"Ca", 40.078 },
|
||||
{"Sc", 44.95591},
|
||||
{"Ti", 47.88 },
|
||||
{"V", 50.9415 },
|
||||
{"Cr", 51.9961 },
|
||||
{"Mn", 54.9381 },
|
||||
{"Fe", 55.847 },
|
||||
{"Co", 58.9332 },
|
||||
{"Ni", 58.69 },
|
||||
{"Cu", 63.546 },
|
||||
{"Zn", 65.39 },
|
||||
{"Ga", 69.723 },
|
||||
{"Ge", 72.61 },
|
||||
{"As", 74.92159},
|
||||
{"Se", 78.96 },
|
||||
{"Br", 79.904 },
|
||||
{"Kr", 83.80 },
|
||||
{"Rb", 85.4678 },
|
||||
{"Sr", 87.62 },
|
||||
{"Y", 88.90585},
|
||||
{"Zr", 91.224 },
|
||||
{"Nb", 92.90638},
|
||||
{"Mo", 95.94 },
|
||||
{"Tc", 97.9072 },
|
||||
{"Ru", 101.07 },
|
||||
{"Rh", 102.9055 },
|
||||
{"Pd", 106.42 },
|
||||
{"Ag", 107.8682 },
|
||||
{"Cd", 112.411 },
|
||||
{"In", 114.82 },
|
||||
{"Sn", 118.710 },
|
||||
{"Sb", 121.75 },
|
||||
{"Te", 127.6 },
|
||||
{"I", 126.90447},
|
||||
{"Xe", 131.29 },
|
||||
{"Cs", 132.90543},
|
||||
{"Ba", 137.327 },
|
||||
{"La", 138.9055 },
|
||||
{"Ce", 140.115 },
|
||||
{"Pr", 140.90765},
|
||||
{"Nd", 144.24 },
|
||||
{"Pm", 144.9127 },
|
||||
{"Sm", 150.36 },
|
||||
{"Eu", 151.965 },
|
||||
{"Gd", 157.25 },
|
||||
{"Tb", 158.92534},
|
||||
{"Dy", 162.50 },
|
||||
{"Ho", 164.93032},
|
||||
{"Er", 167.26 },
|
||||
{"Tm", 168.93421},
|
||||
{"Yb", 173.04 },
|
||||
{"Lu", 174.967 },
|
||||
{"Hf", 178.49 },
|
||||
{"Ta", 180.9479 },
|
||||
{"W", 183.85 },
|
||||
{"Re", 186.207 },
|
||||
{"Os", 190.2 },
|
||||
{"Ir", 192.22 },
|
||||
{"Pt", 195.08 },
|
||||
{"Au", 196.96654},
|
||||
{"Hg", 200.59 },
|
||||
{"Ti", 204.3833 },
|
||||
{"Pb", 207.2 },
|
||||
{"Bi", 208.98037},
|
||||
{"Po", 208.9824 },
|
||||
{"At", 209.9871 },
|
||||
{"Rn", 222.0176 },
|
||||
{"Fr", 223.0197 },
|
||||
{"Ra", 226.0254 },
|
||||
{"Ac", 227.0279 },
|
||||
{"Th", 232.0381 },
|
||||
{"Pa", 231.03588},
|
||||
{"U", 238.0508 },
|
||||
{"Np", 237.0482 },
|
||||
{"Pu", 244.0482 }
|
||||
};
|
||||
|
||||
|
||||
//! Static function to look up an atomic weight
|
||||
/*!
|
||||
*
|
||||
* This static function looks up the argument string in the
|
||||
* database above and returns the associated molecular weight.
|
||||
* The data are from the periodic table.
|
||||
*
|
||||
* Note: The idea behind this function is to provide a unified
|
||||
* source for the element atomic weights. This helps to
|
||||
* ensure that mass is conserved.
|
||||
*
|
||||
* @param
|
||||
* ElemName String. Only the first 3 characters are significant
|
||||
*
|
||||
* @return
|
||||
* Return value contains the atomic weight of the element
|
||||
* If a match for the string is not found, a value of -1.0 is
|
||||
* returned.
|
||||
*
|
||||
* @exception CanteraError
|
||||
* If a match is not found, a CanteraError is thrown as well
|
||||
*/
|
||||
double Elements::LookupWtElements(const std::string& s) {
|
||||
int num = sizeof(aWTable) / sizeof(struct awData);
|
||||
string s3 = s.substr(0,3);
|
||||
for (int i = 0; i < num; i++) {
|
||||
//if (!std::strncmp(s.c_str(), aWTable[i].name, 3)) {
|
||||
if (s3 == aWTable[i].name) {
|
||||
return (aWTable[i].atomicWeight);
|
||||
}
|
||||
}
|
||||
throw CanteraError("LookupWtElements", "element not found");
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
|
||||
//! Exception class to indicate a fixed set of elements.
|
||||
/*!
|
||||
* This class is used to warn the user when the number of elements
|
||||
* are changed after at least one species is defined.
|
||||
*/
|
||||
class ElementsFrozen : public CanteraError {
|
||||
public:
|
||||
//! Constructor for class
|
||||
/*!
|
||||
* @param func Function where the error occurred.
|
||||
*/
|
||||
ElementsFrozen(string func)
|
||||
: CanteraError(func,
|
||||
"elements cannot be added after species.") {}
|
||||
};
|
||||
|
||||
/*
|
||||
* Elements Class Constructor
|
||||
* We initialize all internal variables to zero here.
|
||||
*/
|
||||
Elements::Elements() :
|
||||
m_mm(0),
|
||||
m_elementsFrozen(false),
|
||||
numSubscribers(0)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Elements Class Destructor
|
||||
* If the number of subscribers is not zero, through an error.
|
||||
* A logic problem has occurred.
|
||||
*
|
||||
* @exception CanteraError
|
||||
*/
|
||||
Elements::~Elements()
|
||||
{
|
||||
if (numSubscribers != 0) {
|
||||
throw CanteraError("~Elements", "numSubscribers not zero");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* freezeElements():
|
||||
*
|
||||
* Set the freeze flag. This is a prerequesite to other
|
||||
* activivities, i.e., this is done before species are defined.
|
||||
*/
|
||||
void Elements::freezeElements() {
|
||||
m_elementsFrozen = true;
|
||||
}
|
||||
|
||||
#ifdef INCL_DEPRECATED_METHODS
|
||||
/*
|
||||
*
|
||||
* Returns an ElementData struct that contains the parameters
|
||||
* for element index m.
|
||||
*/
|
||||
ElementData Elements::element(int m) const {
|
||||
ElementData e;
|
||||
e.name = m_elementNames[m];
|
||||
e.atomicWeight = m_atomicWeights[m];
|
||||
return e;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* elementIndex():
|
||||
*
|
||||
* Index of element named \c name. The index is an integer
|
||||
* assigned to each element in the order it was added,
|
||||
* beginning with 0 for the first element. If \c name is not
|
||||
* the name of an element in the set, then the value -1 is
|
||||
* returned.
|
||||
*
|
||||
*/
|
||||
#ifdef USE_DGG_CODE
|
||||
int Elements::elementIndex(std::string name) const{
|
||||
map<string, int>::const_iterator it;
|
||||
it = m_definedElements.find(name);
|
||||
if (it != m_definedElements.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
int Elements::elementIndex(std::string name) const {
|
||||
for (int i = 0; i < m_mm; i++) {
|
||||
if (m_elementNames[i] == name) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
*
|
||||
* Name of the element with index \c m. @param m Element
|
||||
* index. If m < 0 or m >= nElements() an exception is thrown.
|
||||
*/
|
||||
string Elements::elementName(int m) const {
|
||||
if (m >= 0 && m < nElements())
|
||||
return m_elementNames[m];
|
||||
else
|
||||
throw ElementRangeError("Elements::elementName",m,nElements());
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Add an element to the current set of elements in the current object.
|
||||
* @param symbol symbol string
|
||||
* @param weight atomic weight in kg/kmol.
|
||||
*
|
||||
* The default weight is a special value, which will cause the
|
||||
* routine to look up the actual weight via a string lookup.
|
||||
*
|
||||
* There are two interfaces to this routine. The XML interface
|
||||
* looks up the required parameters for the regular interface
|
||||
* and then calls the base routine.
|
||||
*/
|
||||
void Elements::
|
||||
addElement(const std::string& symbol, doublereal weight)
|
||||
{
|
||||
if (weight == -12345.0) {
|
||||
weight = LookupWtElements(symbol);
|
||||
if (weight < 0.0) {
|
||||
throw ElementsFrozen("addElement");
|
||||
}
|
||||
}
|
||||
if (m_elementsFrozen) {
|
||||
throw ElementsFrozen("addElement");
|
||||
return;
|
||||
}
|
||||
m_atomicWeights.push_back(weight);
|
||||
m_elementNames.push_back(symbol);
|
||||
#ifdef USE_DGG_CODE
|
||||
m_definedElements[symbol] = nElements() + 1;
|
||||
#endif
|
||||
m_mm++;
|
||||
}
|
||||
|
||||
void Elements::
|
||||
addElement(const XML_Node& e) {
|
||||
doublereal weight = atof(e["atomicWt"].c_str());
|
||||
string symbol = e["name"];
|
||||
addElement(symbol, weight);
|
||||
}
|
||||
|
||||
/*
|
||||
* addUniqueElement():
|
||||
*
|
||||
* Add a unique element to the set. This routine will not allow
|
||||
* duplicate elements to be input.
|
||||
*
|
||||
* @param symbol symbol string
|
||||
* @param weight atomic weight in kg/kmol.
|
||||
*
|
||||
*
|
||||
* The default weight is a special value, which will cause the
|
||||
* routine to look up the actual weight via a string lookup.
|
||||
*/
|
||||
#ifdef USE_DGG_CODE
|
||||
void Elements::
|
||||
addUniqueElement(const std::string& symbol, doublereal weight, int atomicNumber)
|
||||
{
|
||||
if (m_elementsFrozen)
|
||||
throw ElementsFrozen("addElement");
|
||||
|
||||
if (weight == -12345.0) {
|
||||
weight = LookupWtElements(symbol);
|
||||
}
|
||||
|
||||
/*
|
||||
* First decide if this element has been previously added.
|
||||
* If it unique, add it to the list.
|
||||
*/
|
||||
|
||||
int i = m_definedElements[symbol] - 1;
|
||||
if (i < 0) {
|
||||
m_atomicWeights.push_back(weight);
|
||||
m_elementNames.push_back(symbol);
|
||||
m_atomicNumbers.push_back(atomicNumber);
|
||||
m_mm++;
|
||||
}
|
||||
else {
|
||||
if (m_atomicWeights[i] != weight) {
|
||||
throw CanteraError("AddUniqueElement",
|
||||
"Duplicate Elements (" + symbol +
|
||||
") have different weights");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
void Elements::
|
||||
addUniqueElement(const std::string& symbol,
|
||||
doublereal weight, int atomicNumber)
|
||||
{
|
||||
if (weight == -12345.0) {
|
||||
weight = LookupWtElements(symbol);
|
||||
if (weight < 0.0) {
|
||||
throw ElementsFrozen("addElement");
|
||||
}
|
||||
}
|
||||
/*
|
||||
* First decide if this element has been previously added
|
||||
* by conducting a string search. If it unique, add it to
|
||||
* the list.
|
||||
*/
|
||||
int ifound = 0;
|
||||
int i = 0;
|
||||
for (vector<string>::const_iterator it = m_elementNames.begin();
|
||||
it < m_elementNames.end(); ++it, ++i) {
|
||||
if (*it == symbol) {
|
||||
ifound = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ifound) {
|
||||
if (m_elementsFrozen) {
|
||||
throw ElementsFrozen("addElement");
|
||||
return;
|
||||
}
|
||||
m_atomicWeights.push_back(weight);
|
||||
m_elementNames.push_back(symbol);
|
||||
m_atomicNumbers.push_back(atomicNumber);
|
||||
m_mm++;
|
||||
} else {
|
||||
if (m_atomicWeights[i] != weight) {
|
||||
throw CanteraError("AddUniqueElement",
|
||||
"Duplicate Elements (" + symbol +
|
||||
") have different weights");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* @todo call addUniqueElement(symbol, weight) instead of
|
||||
* addElement.
|
||||
*/
|
||||
void Elements::
|
||||
addUniqueElement(const XML_Node& e) {
|
||||
doublereal weight = 0.0;
|
||||
if (e.hasAttrib("atomicWt"))
|
||||
weight = atof(stripws(e["atomicWt"]).c_str());
|
||||
int anum = 0;
|
||||
if (e.hasAttrib("atomicNumber"))
|
||||
anum = atoi(stripws(e["atomicNumber"]).c_str());
|
||||
string symbol = e["name"];
|
||||
if (weight != 0.0)
|
||||
addUniqueElement(symbol, weight, anum);
|
||||
else
|
||||
addUniqueElement(symbol);
|
||||
}
|
||||
|
||||
/*
|
||||
* clear()
|
||||
*
|
||||
* Remove all elements from the structure.
|
||||
*/
|
||||
void Elements::clear() {
|
||||
m_mm = 0;
|
||||
m_atomicWeights.resize(0);
|
||||
m_elementNames.resize(0);
|
||||
m_elementsFrozen = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* ready():
|
||||
*
|
||||
* True if the elements have been frozen
|
||||
*/
|
||||
bool Elements::ready() const {
|
||||
return (m_elementsFrozen);
|
||||
}
|
||||
|
||||
/*
|
||||
* Elements(const Elements&) - copy constructor:
|
||||
*
|
||||
* This copy constructor just calls the assignment operator for this
|
||||
* class.
|
||||
*/
|
||||
Elements::Elements(const Elements& right)
|
||||
{
|
||||
*this = right;
|
||||
/*
|
||||
* Set the number of subscribers to zero during a copy constructor
|
||||
*/
|
||||
numSubscribers = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Elements& Elements::operator=(const Elements& right):
|
||||
*
|
||||
* (assignment operator)
|
||||
*
|
||||
* This is the assignment operator for the Elements class.
|
||||
* Right now we pretty much do a straight uncomplicated
|
||||
* assignment. However, subscribers are not mucked with, as they
|
||||
* have to do with the address of the object to be subscribed to
|
||||
*/
|
||||
Elements& Elements::operator=(const Elements& right)
|
||||
{
|
||||
/*
|
||||
* Check for self assignment.
|
||||
*/
|
||||
if (this == &right) return *this;
|
||||
/*
|
||||
* We do a straight assignment operator on all of the
|
||||
* data. The vectors are copied.
|
||||
*/
|
||||
m_mm = right.m_mm;
|
||||
m_elementsFrozen = right.m_elementsFrozen;
|
||||
m_atomicWeights = right.m_atomicWeights;
|
||||
m_elementNames = right.m_elementNames;
|
||||
/*
|
||||
* We must not muck with the number of subscribers to this object
|
||||
* during a straight assignment. This number was set in the
|
||||
* constructor operation.
|
||||
*/
|
||||
/*
|
||||
* Return the reference to the current object
|
||||
*/
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void Elements::addElementsFromXML(const XML_Node& phase) {
|
||||
|
||||
// get the declared element names
|
||||
XML_Node& elements = phase.child("elementArray");
|
||||
vector<string> enames;
|
||||
getStringArray(elements, enames);
|
||||
|
||||
// // element database defaults to elements.xml
|
||||
string element_database = "elements.xml";
|
||||
if (elements.hasAttrib("datasrc"))
|
||||
element_database = elements["datasrc"];
|
||||
|
||||
XML_Node* doc = get_XML_File(element_database);
|
||||
XML_Node* dbe = &doc->child("ctml/elementData");
|
||||
|
||||
XML_Node& root = phase.root();
|
||||
XML_Node* local_db = 0;
|
||||
if (root.hasChild("ctml")) {
|
||||
if (root.child("ctml").hasChild("elementData")) {
|
||||
local_db = &root.child("ctml/elementData");
|
||||
}
|
||||
}
|
||||
|
||||
int nel = static_cast<int>(enames.size());
|
||||
int i;
|
||||
string enm;
|
||||
XML_Node* e = 0;
|
||||
for (i = 0; i < nel; i++) {
|
||||
e = 0;
|
||||
if (local_db) {
|
||||
//writelog("looking in local database.");
|
||||
e = local_db->findByAttr("name",enames[i]);
|
||||
//if (!e) writelog(enames[i]+" not found.");
|
||||
}
|
||||
if (!e)
|
||||
e = dbe->findByAttr("name",enames[i]);
|
||||
if (e) {
|
||||
addUniqueElement(*e);
|
||||
}
|
||||
else {
|
||||
throw CanteraError("addElementsFromXML","no data for element "
|
||||
+enames[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* subscribe(), unsubscribe(), and reportSubscriptions():
|
||||
*
|
||||
* Handles setting and reporting the number of subscriptions to this
|
||||
* object.
|
||||
*/
|
||||
void Elements::subscribe() {
|
||||
++numSubscribers;
|
||||
}
|
||||
int Elements::unsubscribe() {
|
||||
--numSubscribers;
|
||||
return numSubscribers;
|
||||
}
|
||||
int Elements::reportSubscriptions() const {
|
||||
return numSubscribers;
|
||||
}
|
||||
|
||||
/********************* GLOBAL STATIC SECTION **************************/
|
||||
/*
|
||||
* We keep track of a vector of pointers to element objects.
|
||||
* Initially there are no Elements objects. Whenever one is created,
|
||||
* the pointer to that object is added onto this list.
|
||||
*/
|
||||
vector<Elements *> Elements::Global_Elements_List;
|
||||
/***********************************************************************/
|
||||
}
|
||||
266
Cantera/src/thermo/Elements.h
Normal file
266
Cantera/src/thermo/Elements.h
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
/**
|
||||
* @file Elements.h
|
||||
* Header file for class, Elements, which contains the elements that
|
||||
* make up species (see \ref phases and \link Cantera::Elements Elements\endlink).
|
||||
*
|
||||
* This file contains the declarations for the elements class.
|
||||
*/
|
||||
/***********************************************************************
|
||||
* $RCSfile$
|
||||
* $Author$
|
||||
* $Date$
|
||||
* $Revision$
|
||||
***********************************************************************/
|
||||
// Copyright 2001 California Institute of Technology
|
||||
|
||||
#ifndef CT_ELEMENTS_H
|
||||
#define CT_ELEMENTS_H
|
||||
|
||||
#undef USE_DGG_CODE
|
||||
|
||||
#include "ct_defs.h"
|
||||
//#include "ctexceptions.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
class XML_Node;
|
||||
class ElementRangeError;
|
||||
|
||||
|
||||
//! Object containing the elements that make up species in a phase.
|
||||
/*!
|
||||
* Class %Elements manages the elements that are part of a
|
||||
* chemistry specification. This class may support calculations
|
||||
* employing Multiple phases. In this case, a single Elements object may
|
||||
* be shared by more than one Constituents class. Reactions between
|
||||
* the phases may then be described using stoichiometry base on the
|
||||
* same Elements class object.
|
||||
*
|
||||
* The member functions return information about the elements described
|
||||
* in a particular instantiation of the class.
|
||||
*
|
||||
* @ingroup phases
|
||||
*/
|
||||
class Elements {
|
||||
|
||||
public:
|
||||
|
||||
/// Default constructor for the elements class
|
||||
Elements();
|
||||
|
||||
//! Default destructor for the elements class
|
||||
~Elements();
|
||||
|
||||
//! Function to lookup the atomic weight of an element
|
||||
/*!
|
||||
* @param ename Element symbol name.
|
||||
*/
|
||||
static double LookupWtElements(const std::string &ename);
|
||||
|
||||
/// Atomic weight of element m.
|
||||
/*!
|
||||
* @param m element index
|
||||
*/
|
||||
doublereal atomicWeight(int m) const { return m_atomicWeights[m]; }
|
||||
|
||||
/// Atomic number of element m.
|
||||
/*!
|
||||
* @param m element index
|
||||
*/
|
||||
int atomicNumber(int m) const { return m_atomicNumbers[m]; }
|
||||
|
||||
/// vector of element atomic weights
|
||||
const vector_fp& atomicWeights() const { return m_atomicWeights; }
|
||||
|
||||
/**
|
||||
* Inline function that returns the number of elements in the object.
|
||||
*
|
||||
* @return
|
||||
* \c int: The number of elements in the object.
|
||||
*/
|
||||
int nElements() const { return m_mm; }
|
||||
|
||||
//! Function that returns the index of an element.
|
||||
/*!
|
||||
* Index of element named \c name. The index is an integer
|
||||
* assigned to each element in the order it was added,
|
||||
* beginning with 0 for the first element. If \c name is not
|
||||
* the name of an element in the set, then the value -1 is
|
||||
* returned.
|
||||
*
|
||||
* @param name String containing the index.
|
||||
*/
|
||||
int elementIndex(std::string name) const;
|
||||
|
||||
//! Name of the element with index \c m.
|
||||
/*!
|
||||
* @param m Element index. If m < 0 or m >= nElements() an exception is thrown.
|
||||
*/
|
||||
std::string elementName(int m) const;
|
||||
|
||||
//! Returns a string vector containing the element names
|
||||
/*!
|
||||
* Returns a read-only reference to the vector of element names.
|
||||
* @return <tt> const vector<string>& </tt>: The vector contains
|
||||
* the element names in their indexed order.
|
||||
*/
|
||||
const std::vector<std::string>& elementNames() const {
|
||||
return m_elementNames;
|
||||
}
|
||||
|
||||
//! Add an element to the current set of elements in the current object.
|
||||
/*!
|
||||
* The default weight is a special value, which will cause the
|
||||
* routine to look up the actual weight via a string lookup.
|
||||
*
|
||||
* There are two interfaces to this routine. The XML interface
|
||||
* looks up the required parameters for the regular interface
|
||||
* and then calls the base routine.
|
||||
*
|
||||
* @param symbol string symbol for the element.
|
||||
* @param weight Atomic weight of the element. If no argument
|
||||
* is provided, a lookup is attempted.
|
||||
*/
|
||||
void addElement(const std::string& symbol,
|
||||
doublereal weight = -12345.0);
|
||||
|
||||
//! Add an element to the current set of elements in the current object.
|
||||
/*!
|
||||
* @param e Reference to the XML_Node containing the element information
|
||||
* The node name is the element symbol and the atomWt attribute
|
||||
* is used as the atomic weight.
|
||||
*/
|
||||
void addElement(const XML_Node& e);
|
||||
|
||||
//! Add an element only if the element hasn't been added before.
|
||||
/*!
|
||||
* This is accomplished via a string match on symbol.
|
||||
*
|
||||
* @param symbol string symbol for the element.
|
||||
* @param weight Atomic weight of the element. If no argument
|
||||
* is provided, a lookup is attempted.
|
||||
* @param atomicNumber defaults to 0
|
||||
*/
|
||||
void addUniqueElement(const std::string& symbol,
|
||||
doublereal weight = -12345.0, int atomicNumber = 0);
|
||||
|
||||
//! Add an element to the current set of elements in the current object.
|
||||
/*!
|
||||
* @param e Reference to the XML_Node containing the element information
|
||||
* The node name is the element symbol and the atomWt attribute
|
||||
* is used as the atomic weight.
|
||||
*/
|
||||
void addUniqueElement(const XML_Node& e);
|
||||
|
||||
//! Add multiple elements from a XML_Node phase description
|
||||
/*!
|
||||
* @param phase XML_Node reference to a phase
|
||||
*/
|
||||
void addElementsFromXML(const XML_Node& phase);
|
||||
|
||||
//! Prohibit addition of more elements, and prepare to add species.
|
||||
void freezeElements();
|
||||
|
||||
/// True if freezeElements has been called.
|
||||
bool elementsFrozen() { return m_elementsFrozen; }
|
||||
|
||||
/// Remove all elements
|
||||
void clear();
|
||||
|
||||
/// True if both elements and species have been frozen
|
||||
bool ready() const;
|
||||
|
||||
//! copy constructor
|
||||
/*!
|
||||
* This copy constructor just calls the assignment operator for this
|
||||
* class. It sets the number of subscribers to zer0.
|
||||
*
|
||||
* @param right Reference to the object to be copied.
|
||||
*/
|
||||
Elements(const Elements& right);
|
||||
|
||||
//! Assigntment operator
|
||||
/*!
|
||||
* This is the assignment operator for the Elements class.
|
||||
* Right now we pretty much do a straight uncomplicated
|
||||
* assignment. However, subscribers are not mucked with, as they
|
||||
* have to do with the address of the object to be subscribed to
|
||||
*
|
||||
* @param right Reference to the object to be copied.
|
||||
*/
|
||||
Elements& operator=(const Elements& right);
|
||||
|
||||
//! subscribe to this object
|
||||
/*!
|
||||
* Increment by one the number of subscriptions to this object.
|
||||
*/
|
||||
void subscribe();
|
||||
|
||||
//! unsubscribe to this object
|
||||
/*!
|
||||
* decrement by one the number of subscriptions to this object.
|
||||
*/
|
||||
int unsubscribe();
|
||||
|
||||
//! report the number of subscriptions
|
||||
int reportSubscriptions() const;
|
||||
|
||||
protected:
|
||||
|
||||
/******************************************************************/
|
||||
/* Description of DATA in the Object */
|
||||
/******************************************************************/
|
||||
|
||||
//! Number of elements.
|
||||
int m_mm;
|
||||
|
||||
/* m_elementsFrozen: */
|
||||
/** boolean indicating completion of object
|
||||
*
|
||||
* If this is true, then no elements may be added to the
|
||||
* object.
|
||||
*/
|
||||
bool m_elementsFrozen;
|
||||
|
||||
/**
|
||||
* Vector of element atomic weights:
|
||||
*
|
||||
* units = kg / kmol
|
||||
*/
|
||||
vector_fp m_atomicWeights;
|
||||
|
||||
/**
|
||||
* Vector of element atomic numbers:
|
||||
*
|
||||
*/
|
||||
vector_int m_atomicNumbers;
|
||||
|
||||
/** Vector of strings containing the names of the elements
|
||||
*
|
||||
* Note, a string search is the primary way to identify elements.
|
||||
*/
|
||||
std::vector<std::string> m_elementNames;
|
||||
|
||||
/**
|
||||
* Number of Constituents Objects that use this object
|
||||
*
|
||||
* Number of Constituents Objects that require this Elements object
|
||||
* to complete its definition.
|
||||
* The destructor checks to see that this is equal to zero.
|
||||
* when the element object is released.
|
||||
*/
|
||||
int numSubscribers;
|
||||
|
||||
/********* GLOBAL STATIC SECTION *************/
|
||||
|
||||
public:
|
||||
/** Vector of pointers to Elements Objects
|
||||
*
|
||||
*/
|
||||
static std::vector<Elements *> Global_Elements_List;
|
||||
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
243
Cantera/src/thermo/GeneralSpeciesThermo.cpp
Normal file
243
Cantera/src/thermo/GeneralSpeciesThermo.cpp
Normal file
|
|
@ -0,0 +1,243 @@
|
|||
/**
|
||||
* @file GeneralSpeciesThermo.cpp
|
||||
* Declarations for a completely general species thermodynamic property
|
||||
* manager for a phase (see \ref spthermo and
|
||||
* \link Cantera::GeneralSpeciesThermo GeneralSpeciesThermo\endlink).
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
// Copyright 2001-2004 California Institute of Technology
|
||||
|
||||
#include "GeneralSpeciesThermo.h"
|
||||
#include "NasaPoly1.h"
|
||||
#include "NasaPoly2.h"
|
||||
#include "ShomatePoly.h"
|
||||
#include "ConstCpPoly.h"
|
||||
#include "Mu0Poly.h"
|
||||
#include "SpeciesThermoFactory.h"
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
|
||||
/*
|
||||
* Constructors
|
||||
*/
|
||||
GeneralSpeciesThermo::GeneralSpeciesThermo() :
|
||||
SpeciesThermo(),
|
||||
m_tlow_max(0.0),
|
||||
m_thigh_min(1.0E30),
|
||||
m_p0(OneAtm),
|
||||
m_kk(0)
|
||||
{
|
||||
m_tlow_max = 0.0;
|
||||
m_thigh_min = 1.0E30;
|
||||
}
|
||||
|
||||
GeneralSpeciesThermo::
|
||||
GeneralSpeciesThermo(const GeneralSpeciesThermo &b) :
|
||||
m_tlow_max(b.m_tlow_max),
|
||||
m_thigh_min(b.m_thigh_min),
|
||||
m_kk(b.m_kk) {
|
||||
m_sp = b.m_sp;
|
||||
}
|
||||
|
||||
const GeneralSpeciesThermo&
|
||||
GeneralSpeciesThermo::operator=(const GeneralSpeciesThermo &b) {
|
||||
if (&b != this) {
|
||||
m_tlow_max = b.m_tlow_max;
|
||||
m_thigh_min = b.m_thigh_min;
|
||||
m_kk = b.m_kk;
|
||||
m_sp = b.m_sp;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
GeneralSpeciesThermo::~GeneralSpeciesThermo() {
|
||||
for (int k = 0; k < m_kk; k++) {
|
||||
SpeciesThermoInterpType *sp = m_sp[k];
|
||||
if (sp) {
|
||||
delete sp;
|
||||
m_sp[k] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SpeciesThermo *
|
||||
GeneralSpeciesThermo::duplMyselfAsSpeciesThermo() const {
|
||||
GeneralSpeciesThermo *gsth = new GeneralSpeciesThermo(*this);
|
||||
return (SpeciesThermo *) gsth;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Install parameterization for a species.
|
||||
* @param index Species index
|
||||
* @param type parameterization type
|
||||
* @param c coefficients. The meaning of these depends on
|
||||
* the parameterization.
|
||||
*/
|
||||
void GeneralSpeciesThermo::install(std::string name,
|
||||
int index,
|
||||
int type,
|
||||
const doublereal* c,
|
||||
doublereal minTemp,
|
||||
doublereal maxTemp,
|
||||
doublereal refPressure) {
|
||||
/*
|
||||
* Resize the arrays if necessary, filling the empty
|
||||
* slots with the zero pointer.
|
||||
*/
|
||||
if (index > m_kk - 1) {
|
||||
m_sp.resize(index+1, 0);
|
||||
m_kk = index+1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the necessary object
|
||||
*/
|
||||
switch (type) {
|
||||
case NASA1:
|
||||
m_sp[index] = new NasaPoly1(index, minTemp, maxTemp,
|
||||
refPressure, c);
|
||||
break;
|
||||
case SHOMATE1:
|
||||
m_sp[index] = new ShomatePoly(index, minTemp, maxTemp,
|
||||
refPressure, c);
|
||||
break;
|
||||
case CONSTANT_CP:
|
||||
case SIMPLE:
|
||||
m_sp[index] = new ConstCpPoly(index, minTemp, maxTemp,
|
||||
refPressure, c);
|
||||
break;
|
||||
case MU0_INTERP:
|
||||
m_sp[index] = new Mu0Poly(index, minTemp, maxTemp,
|
||||
refPressure, c);
|
||||
break;
|
||||
case SHOMATE2:
|
||||
m_sp[index] = new ShomatePoly2(index, minTemp, maxTemp,
|
||||
refPressure, c);
|
||||
break;
|
||||
case NASA2:
|
||||
m_sp[index] = new NasaPoly2(index, minTemp, maxTemp,
|
||||
refPressure, c);
|
||||
break;
|
||||
default:
|
||||
throw UnknownSpeciesThermoModel(
|
||||
"GeneralSpeciesThermo::install",
|
||||
"unknown species type", int2str(type));
|
||||
break;
|
||||
}
|
||||
m_tlow_max = max(minTemp, m_tlow_max);
|
||||
m_thigh_min = min(maxTemp, m_thigh_min);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the properties for one species.
|
||||
*/
|
||||
void GeneralSpeciesThermo::
|
||||
update_one(int k, doublereal t, doublereal* cp_R,
|
||||
doublereal* h_RT, doublereal* s_R) const {
|
||||
SpeciesThermoInterpType * sp_ptr = m_sp[k];
|
||||
sp_ptr->updatePropertiesTemp(t, cp_R, h_RT, s_R);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the properties for all species.
|
||||
*/
|
||||
void GeneralSpeciesThermo::
|
||||
update(doublereal t, doublereal* cp_R,
|
||||
doublereal* h_RT, doublereal* s_R) const {
|
||||
vector<SpeciesThermoInterpType *>::const_iterator _begin, _end;
|
||||
_begin = m_sp.begin();
|
||||
_end = m_sp.end();
|
||||
SpeciesThermoInterpType * sp_ptr;
|
||||
for (; _begin != _end; ++_begin) {
|
||||
sp_ptr = *(_begin);
|
||||
sp_ptr->updatePropertiesTemp(t, cp_R, h_RT, s_R);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This utility function reports the type of parameterization
|
||||
* used for the species, index.
|
||||
*/
|
||||
int GeneralSpeciesThermo::reportType(int index) const {
|
||||
SpeciesThermoInterpType *sp = m_sp[index];
|
||||
return sp->reportType();
|
||||
}
|
||||
|
||||
/**
|
||||
* This utility function reports back the type of
|
||||
* parameterization and all of the parameters for the
|
||||
* species, index.
|
||||
* For the NASA object, there are 15 coefficients.
|
||||
*/
|
||||
void GeneralSpeciesThermo::
|
||||
reportParams(int index, int &type,
|
||||
doublereal * const c,
|
||||
doublereal &minTemp,
|
||||
doublereal &maxTemp,
|
||||
doublereal &refPressure) const {
|
||||
SpeciesThermoInterpType *sp = m_sp[index];
|
||||
int n;
|
||||
sp->reportParameters(n, type, minTemp, maxTemp,
|
||||
refPressure, c);
|
||||
if (n != index) {
|
||||
throw CanteraError(" ", "confused");
|
||||
}
|
||||
}
|
||||
|
||||
//! Modify parameters for the standard state
|
||||
/*!
|
||||
* @param index Species index
|
||||
* @param c Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
*/
|
||||
void GeneralSpeciesThermo::
|
||||
modifyParams(int index, doublereal *c) {
|
||||
SpeciesThermoInterpType *sp = m_sp[index];
|
||||
sp->modifyParameters(c);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the lowest temperature at which the thermodynamic
|
||||
* parameterization is valid. If no argument is supplied, the
|
||||
* value is the one for which all species parameterizations
|
||||
* are valid. Otherwise, if an integer argument is given, the
|
||||
* value applies only to the species with that index.
|
||||
*/
|
||||
doublereal GeneralSpeciesThermo::minTemp(int k) const {
|
||||
if (k < 0)
|
||||
return m_tlow_max;
|
||||
else {
|
||||
SpeciesThermoInterpType *sp = m_sp[k];
|
||||
return sp->minTemp();
|
||||
}
|
||||
}
|
||||
|
||||
doublereal GeneralSpeciesThermo::maxTemp(int k) const {
|
||||
if (k < 0) {
|
||||
return m_thigh_min;
|
||||
} else {
|
||||
SpeciesThermoInterpType *sp = m_sp[k];
|
||||
return sp->maxTemp();
|
||||
}
|
||||
}
|
||||
|
||||
doublereal GeneralSpeciesThermo::refPressure(int k) const {
|
||||
if (k < 0) {
|
||||
return m_p0;
|
||||
} else {
|
||||
SpeciesThermoInterpType *sp = m_sp[k];
|
||||
return sp->refPressure();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
230
Cantera/src/thermo/GeneralSpeciesThermo.h
Normal file
230
Cantera/src/thermo/GeneralSpeciesThermo.h
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
/**
|
||||
* @file GeneralSpeciesThermo.h
|
||||
* Headers for a completely general species thermodynamic property
|
||||
* manager for a phase (see \ref spthermo and
|
||||
* \link Cantera::GeneralSpeciesThermo GeneralSpeciesThermo\endlink).
|
||||
*
|
||||
* Because it is general, it is slow.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
#ifndef CT_GENERALSPECIESTHERMO_H
|
||||
#define CT_GENERALSPECIESTHERMO_H
|
||||
#include <string>
|
||||
#include "ct_defs.h"
|
||||
#include "SpeciesThermoMgr.h"
|
||||
#include "NasaPoly1.h"
|
||||
#include "speciesThermoTypes.h"
|
||||
//#include "polyfit.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
|
||||
//! A species thermodynamic property manager for a phase.
|
||||
/*!
|
||||
* This is a general manager that can handle a wide variety
|
||||
* of species thermodynamic polynomials for individual species.
|
||||
* It is slow, however, because it recomputes the functions of
|
||||
* temperature needed for each species. What it does is to create
|
||||
* a vector of SpeciesThermoInterpType objects.
|
||||
*
|
||||
* @ingroup spthermo
|
||||
*/
|
||||
class GeneralSpeciesThermo : public SpeciesThermo {
|
||||
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
GeneralSpeciesThermo();
|
||||
|
||||
//! Copy constructor
|
||||
GeneralSpeciesThermo(const GeneralSpeciesThermo &);
|
||||
|
||||
//! Assignment operator
|
||||
const GeneralSpeciesThermo & operator=(const GeneralSpeciesThermo &);
|
||||
|
||||
//! destructor
|
||||
virtual ~GeneralSpeciesThermo();
|
||||
|
||||
//! Duplicator
|
||||
virtual SpeciesThermo *duplMyselfAsSpeciesThermo() const ;
|
||||
|
||||
//! Install a new species thermodynamic property
|
||||
//! parameterization for one species.
|
||||
/*!
|
||||
* Install a SpeciesThermoInterpType object for the species, index.
|
||||
* This routine contains an internal list of SpeciesThermoInterpType
|
||||
* objects that it knows about. A factory-type lookup is done
|
||||
* to create the object.
|
||||
*
|
||||
* @param name Name of the species
|
||||
* @param index The 'update' method will update the property
|
||||
* values for this species
|
||||
* at position i index in the property arrays.
|
||||
* @param type int flag specifying the type of parameterization to be
|
||||
* installed.
|
||||
* @param c vector of coefficients for the parameterization.
|
||||
* This vector is simply passed through to the
|
||||
* parameterization constructor. It's length depends upon
|
||||
* the parameterization.
|
||||
* @param minTemp minimum temperature for which this parameterization
|
||||
* is valid.
|
||||
* @param maxTemp maximum temperature for which this parameterization
|
||||
* is valid.
|
||||
* @param refPressure standard-state pressure for this
|
||||
* parameterization.
|
||||
* @see speciesThermoTypes.h
|
||||
*
|
||||
* @todo Create a factory method for SpeciesThermoInterpType.
|
||||
* That's basically what we are doing here.
|
||||
*/
|
||||
virtual void install(std::string name, int index, int type,
|
||||
const doublereal* c,
|
||||
doublereal minTemp, doublereal maxTemp,
|
||||
doublereal refPressure);
|
||||
|
||||
//! 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).
|
||||
*/
|
||||
virtual void update_one(int k, doublereal T, doublereal* cp_R,
|
||||
doublereal* h_RT,
|
||||
doublereal* s_R) const;
|
||||
|
||||
//! Compute the reference-state properties for all species.
|
||||
/*!
|
||||
* Given temperature T in K, this method updates the values of
|
||||
* the non-dimensional heat capacity at constant pressure,
|
||||
* enthalpy, and entropy, at the reference pressure, Pref
|
||||
* of each of the standard states.
|
||||
*
|
||||
* @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).
|
||||
*/
|
||||
virtual void update(doublereal T, doublereal* cp_R,
|
||||
doublereal* h_RT, doublereal* s_R) const;
|
||||
|
||||
//! Minimum temperature.
|
||||
/*!
|
||||
* If no argument is supplied, this
|
||||
* method returns the minimum temperature for which \e all
|
||||
* parameterizations are valid. If an integer index k is
|
||||
* supplied, then the value returned is the minimum
|
||||
* temperature for species k in the phase.
|
||||
*
|
||||
* @param k Species index
|
||||
*/
|
||||
virtual doublereal minTemp(int k=-1) const;
|
||||
|
||||
//! Maximum temperature.
|
||||
/*!
|
||||
* If no argument is supplied, this
|
||||
* method returns the maximum temperature for which \e all
|
||||
* parameterizations are valid. If an integer index k is
|
||||
* supplied, then the value returned is the maximum
|
||||
* temperature for parameterization k.
|
||||
*
|
||||
* @param k Species Index
|
||||
*/
|
||||
virtual doublereal maxTemp(int k=-1) const;
|
||||
|
||||
//! The reference-state pressure for species k.
|
||||
/*!
|
||||
*
|
||||
* returns the reference state pressure in Pascals for
|
||||
* species k. If k is left out of the argument list,
|
||||
* it returns the reference state pressure for the first
|
||||
* species.
|
||||
* Note that some SpeciesThermo implementations, such
|
||||
* as those for ideal gases, require that all species
|
||||
* in the same phase have the same reference state pressures.
|
||||
*
|
||||
* @param k Species Index
|
||||
*/
|
||||
virtual doublereal refPressure(int k = -1) const;
|
||||
|
||||
//! This utility function reports the type of parameterization
|
||||
//! used for the species with index number index.
|
||||
/*!
|
||||
*
|
||||
* @param index Species index
|
||||
*/
|
||||
virtual int reportType(int index) const;
|
||||
|
||||
//! This utility function reports back the type of
|
||||
//! parameterization and all of the parameters for the species, index.
|
||||
/*!
|
||||
* @param index Species index
|
||||
* @param type Integer type of the standard type
|
||||
* @param c Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
* @param minTemp output - Minimum temperature
|
||||
* @param maxTemp output - Maximum temperature
|
||||
* @param refPressure output - reference pressure (Pa).
|
||||
*/
|
||||
virtual void reportParams(int index, int &type,
|
||||
doublereal * const c,
|
||||
doublereal &minTemp,
|
||||
doublereal &maxTemp,
|
||||
doublereal &refPressure) const;
|
||||
|
||||
//! Modify parameters for the standard state
|
||||
/*!
|
||||
* @param index Species index
|
||||
* @param c Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
*/
|
||||
virtual void modifyParams(int index, doublereal *c);
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* This is the main unknown in the object. It is
|
||||
* a list of pointers to type SpeciesThermoInterpType.
|
||||
* Note, this object owns the objects, so they are deleted
|
||||
* in the destructor of this object.
|
||||
*/
|
||||
std::vector<SpeciesThermoInterpType *> m_sp;
|
||||
|
||||
//! Maximum value of the lowest temperature
|
||||
doublereal m_tlow_max;
|
||||
|
||||
//! Minimum value of the highest temperature
|
||||
doublereal m_thigh_min;
|
||||
|
||||
//! reference pressure (Pa)
|
||||
doublereal m_p0;
|
||||
|
||||
/**
|
||||
* Internal variable indicating the length of the
|
||||
* number of species in the phase.
|
||||
*/
|
||||
int m_kk;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -17,7 +17,8 @@
|
|||
#endif
|
||||
|
||||
#include "HMWSoln.h"
|
||||
#include "importCTML.h"
|
||||
//#include "importCTML.h"
|
||||
#include "ThermoFactory.h"
|
||||
#include "WaterProps.h"
|
||||
#include "WaterPDSS.h"
|
||||
#include <math.h>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@
|
|||
*/
|
||||
|
||||
#include "HMWSoln.h"
|
||||
#include "importCTML.h"
|
||||
//#include "importCTML.h"
|
||||
#include "ThermoFactory.h"
|
||||
#include "WaterProps.h"
|
||||
#include "WaterPDSS.h"
|
||||
#include <string.h>
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@
|
|||
#include "xml.h"
|
||||
#include "ctml.h"
|
||||
#include "IdealGasPDSS.h"
|
||||
#include "importCTML.h"
|
||||
|
||||
//#include "importCTML.h"
|
||||
#include "ThermoFactory.h"
|
||||
|
||||
#include "ThermoPhase.h"
|
||||
|
||||
|
|
|
|||
408
Cantera/src/thermo/IdealGasPhase.cpp
Normal file
408
Cantera/src/thermo/IdealGasPhase.cpp
Normal file
|
|
@ -0,0 +1,408 @@
|
|||
/**
|
||||
*
|
||||
* @file IdealGasPhase.cpp
|
||||
* ThermoPhase object for the ideal gas equation of
|
||||
* state - workhorse for %Cantera (see \ref thermoprops
|
||||
* and class \link Cantera::IdealGasPhase IdealGasPhase\endlink).
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma warning(disable:4786)
|
||||
#pragma warning(disable:4503)
|
||||
#endif
|
||||
|
||||
#include "ct_defs.h"
|
||||
#include "mix_defs.h"
|
||||
#include "IdealGasPhase.h"
|
||||
#include "SpeciesThermo.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Cantera {
|
||||
// Empty Constructor
|
||||
IdealGasPhase::IdealGasPhase():
|
||||
m_mm(0),
|
||||
m_tmin(0.0),
|
||||
m_tmax(0.0),
|
||||
m_p0(-1.0),
|
||||
m_tlast(0.0),
|
||||
m_logc0(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
// Molar Thermodynamic Properties of the Solution ----------
|
||||
// Mechanical Equation of State ----------------------------
|
||||
// Chemical Potentials and Activities ----------------------
|
||||
|
||||
/*
|
||||
* Returns the standard concentration \f$ C^0_k \f$, which is used to normalize
|
||||
* the generalized concentration.
|
||||
*/
|
||||
doublereal IdealGasPhase::standardConcentration(int k) const {
|
||||
double p = pressure();
|
||||
return p/(GasConstant * temperature());
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the natural logarithm of the standard
|
||||
* concentration of the kth species
|
||||
*/
|
||||
doublereal IdealGasPhase::logStandardConc(int k) const {
|
||||
_updateThermo();
|
||||
double p = pressure();
|
||||
double lc = std::log (p / (GasConstant * temperature()));
|
||||
return lc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the array of non-dimensional activity coefficients
|
||||
*/
|
||||
void IdealGasPhase::getActivityCoefficients(doublereal *ac) const {
|
||||
for (int k = 0; k < m_kk; k++) {
|
||||
ac[k] = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the array of chemical potentials at unit activity \f$
|
||||
* \mu^0_k(T,P) \f$.
|
||||
*/
|
||||
void IdealGasPhase::getStandardChemPotentials(doublereal* muStar) const {
|
||||
const array_fp& gibbsrt = gibbs_RT_ref();
|
||||
scale(gibbsrt.begin(), gibbsrt.end(), muStar, _RT());
|
||||
double tmp = log (pressure() /m_spthermo->refPressure());
|
||||
tmp *= GasConstant * temperature();
|
||||
for (int k = 0; k < m_kk; k++) {
|
||||
muStar[k] += tmp; // add RT*ln(P/P_0)
|
||||
}
|
||||
}
|
||||
|
||||
// Partial Molar Properties of the Solution --------------
|
||||
|
||||
void IdealGasPhase::getChemPotentials(doublereal* mu) const {
|
||||
getStandardChemPotentials(mu);
|
||||
//doublereal logp = log(pressure()/m_spthermo->refPressure());
|
||||
doublereal xx;
|
||||
doublereal rt = temperature() * GasConstant;
|
||||
//const array_fp& g_RT = gibbs_RT_ref();
|
||||
for (int k = 0; k < m_kk; k++) {
|
||||
xx = fmaxx(SmallNumber, moleFraction(k));
|
||||
mu[k] += rt*(log(xx));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the array of partial molar enthalpies of the species
|
||||
* units = J / kmol
|
||||
*/
|
||||
void IdealGasPhase::getPartialMolarEnthalpies(doublereal* hbar) const {
|
||||
const array_fp& _h = enthalpy_RT_ref();
|
||||
doublereal rt = GasConstant * temperature();
|
||||
scale(_h.begin(), _h.end(), hbar, rt);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the array of partial molar entropies of the species
|
||||
* units = J / kmol / K
|
||||
*/
|
||||
void IdealGasPhase::getPartialMolarEntropies(doublereal* sbar) const {
|
||||
const array_fp& _s = entropy_R_ref();
|
||||
doublereal r = GasConstant;
|
||||
scale(_s.begin(), _s.end(), sbar, r);
|
||||
doublereal logp = log(pressure()/m_spthermo->refPressure());
|
||||
for (int k = 0; k < m_kk; k++) {
|
||||
doublereal xx = fmaxx(SmallNumber, moleFraction(k));
|
||||
sbar[k] += r * (- logp - log(xx));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the array of partial molar internal energies of the species
|
||||
* units = J / kmol
|
||||
*/
|
||||
void IdealGasPhase::getPartialMolarIntEnergies(doublereal* ubar) const {
|
||||
const array_fp& _h = enthalpy_RT_ref();
|
||||
doublereal rt = GasConstant * temperature();
|
||||
for (int k = 0; k < m_kk; k++) {
|
||||
ubar[k] = rt * (_h[k] - 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the array of partial molar heat capacities
|
||||
*/
|
||||
void IdealGasPhase::getPartialMolarCp(doublereal* cpbar) const {
|
||||
const array_fp& _cp = cp_R_ref();
|
||||
scale(_cp.begin(), _cp.end(), cpbar, GasConstant);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the array of partial molar volumes
|
||||
* units = m^3 / kmol
|
||||
*/
|
||||
void IdealGasPhase::getPartialMolarVolumes(doublereal* vbar) const {
|
||||
double vol = 1.0 / molarDensity();
|
||||
for (int k = 0; k < m_kk; k++) {
|
||||
vbar[k] = vol;
|
||||
}
|
||||
}
|
||||
|
||||
// Properties of the Standard State of the Species in the Solution --
|
||||
|
||||
/*
|
||||
* Get the nondimensional Enthalpy functions for the species
|
||||
* at their standard states at the current T and P of the
|
||||
* solution
|
||||
*/
|
||||
void IdealGasPhase::getEnthalpy_RT(doublereal* hrt) const {
|
||||
const array_fp& _h = enthalpy_RT_ref();
|
||||
copy(_h.begin(), _h.end(), hrt);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the array of nondimensional entropy functions for the
|
||||
* standard state species
|
||||
* at the current <I>T</I> and <I>P</I> of the solution.
|
||||
*/
|
||||
void IdealGasPhase::getEntropy_R(doublereal* sr) const {
|
||||
const array_fp& _s = entropy_R_ref();
|
||||
copy(_s.begin(), _s.end(), sr);
|
||||
double tmp = log (pressure() /m_spthermo->refPressure());
|
||||
for (int k = 0; k < m_kk; k++) {
|
||||
sr[k] -= tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the nondimensional gibbs function for the species
|
||||
* standard states at the current T and P of the solution.
|
||||
*/
|
||||
void IdealGasPhase::getGibbs_RT(doublereal* grt) const {
|
||||
const array_fp& gibbsrt = gibbs_RT_ref();
|
||||
copy(gibbsrt.begin(), gibbsrt.end(), grt);
|
||||
double tmp = log (pressure() /m_spthermo->refPressure());
|
||||
for (int k = 0; k < m_kk; k++) {
|
||||
grt[k] += tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* get the pure Gibbs free energies of each species assuming
|
||||
* it is in its standard state. This is the same as
|
||||
* getStandardChemPotentials().
|
||||
*/
|
||||
void IdealGasPhase::getPureGibbs(doublereal* gpure) const {
|
||||
const array_fp& gibbsrt = gibbs_RT_ref();
|
||||
scale(gibbsrt.begin(), gibbsrt.end(), gpure, _RT());
|
||||
double tmp = log (pressure() /m_spthermo->refPressure());
|
||||
tmp *= _RT();
|
||||
for (int k = 0; k < m_kk; k++) {
|
||||
gpure[k] += tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the vector of nondimensional
|
||||
* internal Energies of the standard state at the current temperature
|
||||
* and pressure of the solution for each species.
|
||||
*/
|
||||
void IdealGasPhase::getIntEnergy_RT(doublereal *urt) const {
|
||||
const array_fp& _h = enthalpy_RT_ref();
|
||||
for (int k = 0; k < m_kk; k++) {
|
||||
urt[k] = _h[k] - 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the nondimensional heat capacity at constant pressure
|
||||
* function for the species
|
||||
* standard states at the current T and P of the solution.
|
||||
*/
|
||||
void IdealGasPhase::getCp_R(doublereal* cpr) const {
|
||||
const array_fp& _cpr = cp_R_ref();
|
||||
copy(_cpr.begin(), _cpr.end(), cpr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the molar volumes of the species standard states at the current
|
||||
* <I>T</I> and <I>P</I> of the solution.
|
||||
* units = m^3 / kmol
|
||||
*
|
||||
* @param vol Output vector containing the standard state volumes.
|
||||
* Length: m_kk.
|
||||
*/
|
||||
void IdealGasPhase::getStandardVolumes(doublereal *vol) const {
|
||||
double tmp = 1.0 / molarDensity();
|
||||
for (int k = 0; k < m_kk; k++) {
|
||||
vol[k] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
// Thermodynamic Values for the Species Reference States ---------
|
||||
|
||||
/*
|
||||
* Returns the vector of nondimensional
|
||||
* enthalpies of the reference state at the current temperature
|
||||
* and reference presssure.
|
||||
*/
|
||||
void IdealGasPhase::getEnthalpy_RT_ref(doublereal *hrt) const {
|
||||
const array_fp& _h = enthalpy_RT_ref();
|
||||
copy(_h.begin(), _h.end(), hrt);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the vector of nondimensional
|
||||
* enthalpies of the reference state at the current temperature
|
||||
* and reference pressure.
|
||||
*/
|
||||
void IdealGasPhase::getGibbs_RT_ref(doublereal *grt) const {
|
||||
const array_fp& gibbsrt = gibbs_RT_ref();
|
||||
copy(gibbsrt.begin(), gibbsrt.end(), grt);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the vector of the
|
||||
* gibbs function of the reference state at the current temperature
|
||||
* and reference pressure.
|
||||
* units = J/kmol
|
||||
*/
|
||||
void IdealGasPhase::getGibbs_ref(doublereal *g) const {
|
||||
const array_fp& gibbsrt = gibbs_RT_ref();
|
||||
scale(gibbsrt.begin(), gibbsrt.end(), g, _RT());
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the vector of nondimensional
|
||||
* entropies of the reference state at the current temperature
|
||||
* and reference pressure.
|
||||
*/
|
||||
void IdealGasPhase::getEntropy_R_ref(doublereal *er) const {
|
||||
const array_fp& _s = entropy_R_ref();
|
||||
copy(_s.begin(), _s.end(), er);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the vector of nondimensional
|
||||
* internal Energies of the reference state at the current temperature
|
||||
* of the solution and the reference pressure for each species.
|
||||
*/
|
||||
void IdealGasPhase::getIntEnergy_RT_ref(doublereal *urt) const {
|
||||
const array_fp& _h = enthalpy_RT_ref();
|
||||
for (int k = 0; k < m_kk; k++) {
|
||||
urt[k] = _h[k] - 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the vector of nondimensional
|
||||
* constant pressure heat capacities of the reference state
|
||||
* at the current temperature and reference pressure.
|
||||
*/
|
||||
void IdealGasPhase::getCp_R_ref(doublereal *cprt) const {
|
||||
const array_fp& _cpr = cp_R_ref();
|
||||
copy(_cpr.begin(), _cpr.end(), cprt);
|
||||
}
|
||||
|
||||
void IdealGasPhase::getStandardVolumes_ref(doublereal *vol) const {
|
||||
doublereal tmp = _RT() / m_p0;
|
||||
for (int k = 0; k < m_kk; k++) {
|
||||
vol[k] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// new methods defined here -------------------------------
|
||||
|
||||
|
||||
void IdealGasPhase::initThermo() {
|
||||
|
||||
m_mm = nElements();
|
||||
doublereal tmin = m_spthermo->minTemp();
|
||||
doublereal tmax = m_spthermo->maxTemp();
|
||||
if (tmin > 0.0) m_tmin = tmin;
|
||||
if (tmax > 0.0) m_tmax = tmax;
|
||||
m_p0 = refPressure();
|
||||
|
||||
int leng = m_kk;
|
||||
m_h0_RT.resize(leng);
|
||||
m_g0_RT.resize(leng);
|
||||
m_expg0_RT.resize(leng);
|
||||
m_cp0_R.resize(leng);
|
||||
m_s0_R.resize(leng);
|
||||
m_pe.resize(leng, 0.0);
|
||||
m_pp.resize(leng);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set mixture to an equilibrium state consistent with specified
|
||||
* chemical potentials and temperature. This method is needed by
|
||||
* the ChemEquil equillibrium solver.
|
||||
*/
|
||||
void IdealGasPhase::setToEquilState(const doublereal* mu_RT)
|
||||
{
|
||||
double tmp, tmp2;
|
||||
const array_fp& grt = gibbs_RT_ref();
|
||||
|
||||
/*
|
||||
* Within the method, we protect against inf results if the
|
||||
* exponent is too high.
|
||||
*
|
||||
* If it is too low, we set
|
||||
* the partial pressure to zero. This capability is needed
|
||||
* by the elemental potential method.
|
||||
*/
|
||||
doublereal pres = 0.0;
|
||||
for (int k = 0; k < m_kk; k++) {
|
||||
tmp = -grt[k] + mu_RT[k];
|
||||
if (tmp < -600.) {
|
||||
m_pp[k] = 0.0;
|
||||
} else if (tmp > 500.0) {
|
||||
tmp2 = tmp / 500.;
|
||||
tmp2 *= tmp2;
|
||||
m_pp[k] = m_p0 * exp(500.) * tmp2;
|
||||
} else {
|
||||
m_pp[k] = m_p0 * exp(tmp);
|
||||
}
|
||||
pres += m_pp[k];
|
||||
}
|
||||
// set state
|
||||
setState_PX(pres, &m_pp[0]);
|
||||
}
|
||||
|
||||
|
||||
/// This method is called each time a thermodynamic property is
|
||||
/// requested, to check whether the internal species properties
|
||||
/// within the object need to be updated.
|
||||
/// Currently, this updates the species thermo polynomial values
|
||||
/// for the current value of the temperature. A check is made
|
||||
/// to see if the temperature has changed since the last
|
||||
/// evaluation. This object does not contain any persistent
|
||||
/// data that depends on the concentration, that needs to be
|
||||
/// updated. The state object modifies its concentration
|
||||
/// dependent information at the time the setMoleFractions()
|
||||
/// (or equivalent) call is made.
|
||||
void IdealGasPhase::_updateThermo() const {
|
||||
doublereal tnow = temperature();
|
||||
|
||||
// If the temperature has changed since the last time these
|
||||
// properties were computed, recompute them.
|
||||
if (m_tlast != tnow) {
|
||||
m_spthermo->update(tnow, &m_cp0_R[0], &m_h0_RT[0],
|
||||
&m_s0_R[0]);
|
||||
m_tlast = tnow;
|
||||
|
||||
// update the species Gibbs functions
|
||||
int k;
|
||||
for (k = 0; k < m_kk; k++) {
|
||||
m_g0_RT[k] = m_h0_RT[k] - m_s0_R[k];
|
||||
}
|
||||
m_logc0 = log(m_p0/(GasConstant * tnow));
|
||||
m_tlast = tnow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
930
Cantera/src/thermo/IdealGasPhase.h
Normal file
930
Cantera/src/thermo/IdealGasPhase.h
Normal file
|
|
@ -0,0 +1,930 @@
|
|||
/**
|
||||
* @file IdealGasPhase.h
|
||||
* ThermoPhase object for the ideal gas equation of
|
||||
* state - workhorse for %Cantera (see \ref thermoprops
|
||||
* and class \link Cantera::IdealGasPhase IdealGasPhase\endlink).
|
||||
*
|
||||
*/
|
||||
|
||||
/* $Author$
|
||||
* $Date$
|
||||
* $Revision$
|
||||
*
|
||||
* Copyright 2001 California Institute of Technology
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CT_IDEALGASPHASE_H
|
||||
#define CT_IDEALGASPHASE_H
|
||||
|
||||
//#include "ct_defs.h"
|
||||
#include "mix_defs.h"
|
||||
#include "ThermoPhase.h"
|
||||
#include "SpeciesThermo.h"
|
||||
#include "utilities.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
|
||||
//! Class %IdealGasPhase represents low-density gases that obey the
|
||||
//! ideal gas equation of state.
|
||||
/*!
|
||||
*
|
||||
* %IdealGasPhase derives from class ThermoPhase,
|
||||
* and overloads the virtual methods defined there with ones that
|
||||
* use expressions appropriate for ideal gas mixtures.
|
||||
*
|
||||
* The independent unknowns are density, mass fraction, and temperature.
|
||||
* the #setPressure() function will calculate the density consistent with
|
||||
* the current mass fraction vector and temperature and the desired pressure,
|
||||
* and then set the density in the derived State object.
|
||||
*
|
||||
* <HR>
|
||||
* <H2> Specification of Species Standard %State Properties </H2>
|
||||
* <HR>
|
||||
*
|
||||
* It is assumed that the reference state thermodynamics may be
|
||||
* obtained by a pointer to a populated species thermodynamic property
|
||||
* manager class in the base class, ThermoPhase::m_spthermo
|
||||
* (see the base class \link Cantera#SpeciesThermo SpeciesThermo \endlink for a
|
||||
* description of the specification of reference state species thermodynamics functions).
|
||||
* The reference state,
|
||||
* where the pressure is fixed at a single pressure,
|
||||
* is a key species property calculation for the Ideal Gas Equation
|
||||
* of state.
|
||||
*
|
||||
* This class is optimized for speed of execution. All calls to thermodynamic functions
|
||||
* first call internal routines (aka #enthalpy_RT_ref()) which return references
|
||||
* the reference state thermodynamics functions. Within these internal reference
|
||||
* state functions, the function #_updateThermo() is called, that first checks to see
|
||||
* whether the temperature has changed. If it has, it updates the internal reference
|
||||
* state thermo functions by calling the SpeciesThermo object.
|
||||
*
|
||||
* Functions for the calculation of standard state properties for species
|
||||
* at arbitray pressure are provided in %IdealGasPhase. However, they
|
||||
* are all derived from their reference state conterparts.
|
||||
*
|
||||
* The standard state enthalpy is independent of pressure:
|
||||
*
|
||||
* \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]
|
||||
*
|
||||
* The molar volume of a species is given by the ideal gas law
|
||||
*
|
||||
* \f[
|
||||
* V^o_k(T,P) = \frac{R T}{P} \mbox{\quad where}
|
||||
* \f]
|
||||
*
|
||||
* R = 8314.47215 Joules kmol<SUP>-1</SUP> K<SUP>-1</SUP>, from the 1999 CODATA convention.
|
||||
* For a complete list of physical constants used within %Cantera, see \ref physConstants .
|
||||
*
|
||||
* <HR>
|
||||
* <H2> Specification of Solution Thermodynamic Properties </H2>
|
||||
* <HR>
|
||||
*
|
||||
* The activity of a species defined in the phase is given by the ideal gas law:
|
||||
* \f[
|
||||
* a_k = X_k
|
||||
* \f]
|
||||
* where \f$ X_k \f$ is the mole fraction of species <I>k</I>.
|
||||
* The chemical potential for species <I>k</I> is equal to
|
||||
*
|
||||
* \f[
|
||||
* \mu_k(T,P) = \mu^o_k(T, P) + R T \log(X_k)
|
||||
* \f]
|
||||
*
|
||||
* In terms of the reference state, the above can be rewritten
|
||||
*
|
||||
*
|
||||
* \f[
|
||||
* \mu_k(T,P) = \mu^{ref}_k(T, P) + R T \log(\frac{P X_k}{P_{ref}})
|
||||
* \f]
|
||||
*
|
||||
* The partial molar entropy for species <I>k</I> is given by the following relation,
|
||||
*
|
||||
* \f[
|
||||
* \tilde{s}_k(T,P) = s^o_k(T,P) - R \log(X_k) = s^{ref}_k(T) - R \log(\frac{P X_k}{P_{ref}})
|
||||
* \f]
|
||||
*
|
||||
* The partial molar enthalpy for species <I>k</I> is
|
||||
*
|
||||
* \f[
|
||||
* \tilde{h}_k(T,P) = h^o_k(T,P) = h^{ref}_k(T)
|
||||
* \f]
|
||||
*
|
||||
* The partial molar Internal Energy for species <I>k</I> is
|
||||
*
|
||||
* \f[
|
||||
* \tilde{u}_k(T,P) = u^o_k(T,P) = u^{ref}_k(T)
|
||||
* \f]
|
||||
*
|
||||
* The partial molar Heat Capacity for species <I>k</I> is
|
||||
*
|
||||
* \f[
|
||||
* \tilde{Cp}_k(T,P) = Cp^o_k(T,P) = Cp^{ref}_k(T)
|
||||
* \f]
|
||||
*
|
||||
*
|
||||
* <HR>
|
||||
* <H2> %Application within %Kinetics Managers </H2>
|
||||
* <HR>
|
||||
*
|
||||
* \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 <I>k</I> is independent of <I>k</I> 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.
|
||||
*
|
||||
* <HR>
|
||||
* <H2> Instantiation of the Class </H2>
|
||||
* <HR>
|
||||
*
|
||||
*
|
||||
* The constructor for this phase is located in the default ThermoFactory
|
||||
* for %Cantera. A new %IdealGasPhase may be created by the following code snippet:
|
||||
*
|
||||
* @code
|
||||
* XML_Node *xc = get_XML_File("silane.xml");
|
||||
* XML_Node * const xs = xc->findNameID("phase", "silane");
|
||||
* ThermoPhase *silane_tp = newPhase(*xs);
|
||||
* IdealGasPhase *silaneGas = dynamic_cast <IdealGasPhase *>(silane_tp);
|
||||
* @endcode
|
||||
*
|
||||
* or by the following constructor:
|
||||
*
|
||||
* @code
|
||||
* XML_Node *xc = get_XML_File("silane.xml");
|
||||
* XML_Node * const xs = xc->findNameID("phase", "silane");
|
||||
* IdealGasPhase *silaneGas = new IdealGasPhase(*xs);
|
||||
* @endcode
|
||||
*
|
||||
* <HR>
|
||||
* <H2> XML Example </H2>
|
||||
* <HR>
|
||||
* An example of an XML Element named phase setting up a IdealGasPhase object named silane
|
||||
* is given below.
|
||||
*
|
||||
* @verbatim
|
||||
<!-- phase silane -->
|
||||
<phase dim="3" id="silane">
|
||||
<elementArray datasrc="elements.xml"> Si H He </elementArray>
|
||||
<speciesArray datasrc="#species_data">
|
||||
H2 H HE SIH4 SI SIH SIH2 SIH3 H3SISIH SI2H6
|
||||
H2SISIH2 SI3H8 SI2 SI3
|
||||
</speciesArray>
|
||||
<reactionArray datasrc="#reaction_data"/>
|
||||
<thermo model="IdealGas"/>
|
||||
<kinetics model="GasKinetics"/>
|
||||
<transport model="None"/>
|
||||
</phase>
|
||||
@endverbatim
|
||||
*
|
||||
* The model attribute "IdealGas" of the thermo XML element identifies the phase as
|
||||
* being of the type handled by the IdealGasPhase object.
|
||||
*
|
||||
* @ingroup thermoprops
|
||||
*
|
||||
*/
|
||||
class IdealGasPhase : public ThermoPhase {
|
||||
|
||||
public:
|
||||
|
||||
//! Empty Constructor
|
||||
IdealGasPhase();
|
||||
|
||||
//! Destructor
|
||||
virtual ~IdealGasPhase() {}
|
||||
|
||||
//! Equation of state flag.
|
||||
/*!
|
||||
* Returns the value cIdealGas, defined in mix_defs.h.
|
||||
*/
|
||||
virtual int eosType() const { return cIdealGas; }
|
||||
|
||||
/**
|
||||
* @name Molar Thermodynamic Properties of the Solution ------------------------------
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
//! Return the Molar enthalpy. Units: J/kmol.
|
||||
/*!
|
||||
* For an ideal gas mixture,
|
||||
* \f[
|
||||
* \hat h(T) = \sum_k X_k \hat h^0_k(T),
|
||||
* \f]
|
||||
* and is a function only of temperature.
|
||||
* The standard-state pure-species enthalpies
|
||||
* \f$ \hat h^0_k(T) \f$ are computed by the species thermodynamic
|
||||
* property manager.
|
||||
*
|
||||
* \see SpeciesThermo
|
||||
*/
|
||||
virtual doublereal enthalpy_mole() const {
|
||||
return GasConstant * temperature() *
|
||||
mean_X(&enthalpy_RT_ref()[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Molar internal energy. J/kmol. For an ideal gas mixture,
|
||||
* \f[
|
||||
* \hat u(T) = \sum_k X_k \hat h^0_k(T) - \hat R T,
|
||||
* \f]
|
||||
* and is a function only of temperature.
|
||||
* The reference-state pure-species enthalpies
|
||||
* \f$ \hat h^0_k(T) \f$ are computed by the species thermodynamic
|
||||
* property manager.
|
||||
* @see SpeciesThermo
|
||||
*/
|
||||
virtual doublereal intEnergy_mole() const {
|
||||
return GasConstant * temperature()
|
||||
* ( mean_X(&enthalpy_RT_ref()[0]) - 1.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Molar entropy. Units: J/kmol/K.
|
||||
* For an ideal gas mixture,
|
||||
* \f[
|
||||
* \hat s(T, P) = \sum_k X_k \hat s^0_k(T) - \hat R \log (P/P^0).
|
||||
* \f]
|
||||
* The reference-state pure-species entropies
|
||||
* \f$ \hat s^0_k(T) \f$ are computed by the species thermodynamic
|
||||
* property manager.
|
||||
* @see SpeciesThermo
|
||||
*/
|
||||
virtual doublereal entropy_mole() const {
|
||||
return GasConstant * (mean_X(&entropy_R_ref()[0]) -
|
||||
sum_xlogx() - std::log(pressure()/m_spthermo->refPressure()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Molar Gibbs free Energy for an ideal gas.
|
||||
* Units = J/kmol.
|
||||
*/
|
||||
virtual doublereal gibbs_mole() const {
|
||||
return enthalpy_mole() - temperature() * entropy_mole();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Molar heat capacity at constant pressure. Units: J/kmol/K.
|
||||
* For an ideal gas mixture,
|
||||
* \f[
|
||||
* \hat c_p(t) = \sum_k \hat c^0_{p,k}(T).
|
||||
* \f]
|
||||
* The reference-state pure-species heat capacities
|
||||
* \f$ \hat c^0_{p,k}(T) \f$ are computed by the species thermodynamic
|
||||
* property manager.
|
||||
* @see SpeciesThermo
|
||||
*/
|
||||
virtual doublereal cp_mole() const {
|
||||
return GasConstant * mean_X(&cp_R_ref()[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Molar heat capacity at constant volume. Units: J/kmol/K.
|
||||
* For an ideal gas mixture,
|
||||
* \f[ \hat c_v = \hat c_p - \hat R. \f]
|
||||
*/
|
||||
virtual doublereal cv_mole() const {
|
||||
return cp_mole() - GasConstant;
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
/**
|
||||
* @name Mechanical Equation of State ------------------------------------------------
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Pressure. Units: Pa.
|
||||
* For an ideal gas mixture,
|
||||
* \f[ P = n \hat R T. \f]
|
||||
*/
|
||||
virtual doublereal pressure() const {
|
||||
return GasConstant * molarDensity() * temperature();
|
||||
}
|
||||
|
||||
|
||||
//! Set the pressure at constant temperature and composition.
|
||||
/*!
|
||||
* Units: Pa.
|
||||
* This method is implemented by setting the mass density to
|
||||
* \f[
|
||||
* \rho = \frac{P \overline W}{\hat R T }.
|
||||
* \f]
|
||||
*
|
||||
* @param p Pressure (Pa)
|
||||
*/
|
||||
virtual void setPressure(doublereal p) {
|
||||
setDensity(p * meanMolecularWeight()
|
||||
/(GasConstant * temperature()));
|
||||
}
|
||||
|
||||
//! Returns the isothermal compressibility. Units: 1/Pa.
|
||||
/**
|
||||
* The isothermal compressibility is defined as
|
||||
* \f[
|
||||
* \kappa_T = -\frac{1}{v}\left(\frac{\partial v}{\partial P}\right)_T
|
||||
* \f]
|
||||
* For ideal gases it's equal to the negative of the inverse of the pressure
|
||||
*/
|
||||
virtual doublereal isothermalCompressibility() const {
|
||||
return -1.0/pressure();
|
||||
}
|
||||
|
||||
//! Return the volumetric thermal expansion coefficient. Units: 1/K.
|
||||
/*!
|
||||
* The thermal expansion coefficient is defined as
|
||||
* \f[
|
||||
* \beta = \frac{1}{v}\left(\frac{\partial v}{\partial T}\right)_P
|
||||
* \f]
|
||||
* For ideal gases, it's equal to the inverse of the temperature.
|
||||
*/
|
||||
virtual doublereal thermalExpansionCoeff() const {
|
||||
return 1.0/temperature();
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
/**
|
||||
* @name Chemical Potentials and Activities ------------------------------------------
|
||||
*
|
||||
*
|
||||
* The activity \f$a_k\f$ of a species in solution is
|
||||
* related to the chemical potential by
|
||||
* \f[
|
||||
* \mu_k(T,P,X_k) = \mu_k^0(T,P)
|
||||
* + \hat R T \log a_k.
|
||||
* \f]
|
||||
* The quantity \f$\mu_k^0(T,P)\f$ is
|
||||
* the standard state chemical potential at unit activity.
|
||||
* It may depend on the pressure and the temperature. However,
|
||||
* it may not depend on the mole fractions of the species
|
||||
* in the solution.
|
||||
*
|
||||
* The activities are related to the generalized
|
||||
* concentrations, \f$\tilde C_k\f$, and standard
|
||||
* concentrations, \f$C^0_k\f$, by the following formula:
|
||||
*
|
||||
* \f[
|
||||
* a_k = \frac{\tilde C_k}{C^0_k}
|
||||
* \f]
|
||||
* The generalized concentrations are used in the kinetics classes
|
||||
* to describe the rates of progress of reactions involving the
|
||||
* species. Their formulation depends upons the specification
|
||||
* of the rate constants for reaction, especially the units used
|
||||
* in specifying the rate constants. The bridge between the
|
||||
* thermodynamic equilibrium expressions that use a_k and the
|
||||
* kinetics expressions which use the generalized concentrations
|
||||
* is provided by the multiplicative factor of the
|
||||
* standard concentrations.
|
||||
* @{
|
||||
*/
|
||||
|
||||
//! This method returns the array of generalized concentrations.
|
||||
/*!
|
||||
* For an ideal gas mixture, these are simply the actual concentrations.
|
||||
*
|
||||
* @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 {
|
||||
getConcentrations(c);
|
||||
}
|
||||
|
||||
//! Returns the standard concentration \f$ C^0_k \f$, which is used to normalize
|
||||
//! the generalized concentration.
|
||||
/*!
|
||||
* This is defined as the concentration by which the generalized
|
||||
* concentration is normalized to produce the activity.
|
||||
* In many cases, this quantity will be the same for all species in a phase.
|
||||
* Since the activity for an ideal gas mixture is
|
||||
* simply the mole fraction, for an ideal gas \f$ C^0_k = P/\hat R T \f$.
|
||||
*
|
||||
* @param k Optional parameter indicating the species. The default
|
||||
* is to assume this refers to species 0.
|
||||
* @return
|
||||
* Returns the standard Concentration in units of m3 kmol-1.
|
||||
*/
|
||||
virtual doublereal standardConcentration(int k=0) const;
|
||||
|
||||
//! Returns the natural logarithm of the standard
|
||||
//! concentration of the kth species
|
||||
/*!
|
||||
* @param k index of the species. (defaults to zero)
|
||||
*/
|
||||
virtual doublereal logStandardConc(int k=0) const;
|
||||
|
||||
//! Get the array of non-dimensional activity coefficients at
|
||||
//! the current solution temperature, pressure, and solution concentration.
|
||||
/*!
|
||||
* For ideal gases, the activity coefficients are all equal to one.
|
||||
*
|
||||
* @param ac Output vector of activity coefficients. Length: m_kk.
|
||||
*/
|
||||
virtual void getActivityCoefficients(doublereal* ac) const;
|
||||
|
||||
|
||||
//@}
|
||||
/// @name Partial Molar Properties of the Solution ----------------------------------
|
||||
//@{
|
||||
|
||||
|
||||
//! Get the species chemical potentials. Units: J/kmol.
|
||||
/*!
|
||||
* This function returns a vector of chemical potentials of the
|
||||
* species in solution at the current temperature, pressure
|
||||
* and mole fraction of the solution.
|
||||
*
|
||||
* @param mu Output vector of species chemical
|
||||
* potentials. Length: m_kk. Units: J/kmol
|
||||
*/
|
||||
virtual void getChemPotentials(doublereal* mu) const;
|
||||
|
||||
//! Get the species partial molar enthalpies. Units: J/kmol.
|
||||
/*!
|
||||
* @param hbar Output vector of species partial molar enthalpies.
|
||||
* Length: m_kk. units are J/kmol.
|
||||
*/
|
||||
virtual void getPartialMolarEnthalpies(doublereal* hbar) const;
|
||||
|
||||
//! Get the species partial molar entropies. Units: J/kmol/K.
|
||||
/*!
|
||||
* @param sbar Output vector of species partial molar entropies.
|
||||
* Length = m_kk. units are J/kmol/K.
|
||||
*/
|
||||
virtual void getPartialMolarEntropies(doublereal* sbar) const;
|
||||
|
||||
//! Get the species partial molar enthalpies. Units: J/kmol.
|
||||
/*!
|
||||
* @param ubar Output vector of speciar partial molar internal energies.
|
||||
* Length = m_kk. units are J/kmol.
|
||||
*/
|
||||
virtual void getPartialMolarIntEnergies(doublereal* ubar) const;
|
||||
|
||||
//! Get the partial molar heat capacities Units: J/kmol/K
|
||||
/*!
|
||||
* @param cpbar Output vector of species partial molar heat capacities at constant pressure.
|
||||
* Length = m_kk. units are J/kmol/K.
|
||||
*/
|
||||
virtual void getPartialMolarCp(doublereal* cpbar) const;
|
||||
|
||||
//! Get the species partial molar volumes. Units: m^3/kmol.
|
||||
/*!
|
||||
* @param vbar Output vector of speciar partial molar volumes.
|
||||
* Length = m_kk. units are m^3/kmol.
|
||||
*/
|
||||
virtual void getPartialMolarVolumes(doublereal* vbar) const;
|
||||
|
||||
//@}
|
||||
/// @name Properties of the Standard State of the Species in the Solution ----------
|
||||
//@{
|
||||
|
||||
//! Get the array of chemical potentials at unit activity for the
|
||||
//! species standard states at the current <I>T</I> and <I>P</I> of the solution.
|
||||
/*!
|
||||
* 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 mu Output vector of chemical potentials.
|
||||
* Length: m_kk.
|
||||
*/
|
||||
virtual void getStandardChemPotentials(doublereal* mu) const;
|
||||
|
||||
//! Get the nondimensional Enthalpy functions for the species standard states
|
||||
//! at their standard states at the current <I>T</I> and <I>P</I> of the solution.
|
||||
/*!
|
||||
* @param hrt Output vector of nondimensional standard state enthalpies.
|
||||
* Length: m_kk.
|
||||
*/
|
||||
virtual void getEnthalpy_RT(doublereal* hrt) const;
|
||||
|
||||
//! Get the array of nondimensional Entropy functions for the
|
||||
//! species standard states at the current <I>T</I> and <I>P</I> of the solution.
|
||||
/*!
|
||||
* @param sr Output vector of nondimensional standard state entropies.
|
||||
* Length: m_kk.
|
||||
*/
|
||||
virtual void getEntropy_R(doublereal* sr) const;
|
||||
|
||||
//! Get the nondimensional Gibbs functions for the species
|
||||
//! standard states at the current <I>T</I> and <I>P</I> of the solution.
|
||||
/*!
|
||||
* @param grt Output vector of nondimensional standard state gibbs free energies
|
||||
* Length: m_kk.
|
||||
*/
|
||||
virtual void getGibbs_RT(doublereal* grt) const;
|
||||
|
||||
//! Get the Gibbs functions for the standard
|
||||
//! state of the species at the current <I>T</I> and <I>P</I> of the solution
|
||||
/*!
|
||||
* Units are Joules/kmol
|
||||
* @param gpure Output vector of standard state gibbs free energies
|
||||
* Length: m_kk.
|
||||
*/
|
||||
virtual void getPureGibbs(doublereal* gpure) const;
|
||||
|
||||
//! Returns the vector of nondimensional Internal Energies of the standard
|
||||
//! state species at the current <I>T</I> and <I>P</I> of the solution
|
||||
/*!
|
||||
* @param urt output vector of nondimensional standard state internal energies
|
||||
* of the species. Length: m_kk.
|
||||
*/
|
||||
virtual void getIntEnergy_RT(doublereal *urt) const;
|
||||
|
||||
//! Get the nondimensional Heat Capacities at constant
|
||||
//! pressure for the species standard states
|
||||
//! at the current <I>T</I> and <I>P</I> of the solution
|
||||
/*!
|
||||
* @param cpr Output vector of nondimensional standard state heat capacities
|
||||
* Length: m_kk.
|
||||
*/
|
||||
virtual void getCp_R(doublereal* cpr) const;
|
||||
|
||||
//! Get the molar volumes of the species standard states at the current
|
||||
//! <I>T</I> and <I>P</I> of the solution.
|
||||
/*!
|
||||
* units = m^3 / kmol
|
||||
*
|
||||
* @param vol Output vector containing the standard state volumes.
|
||||
* Length: m_kk.
|
||||
*/
|
||||
virtual void getStandardVolumes(doublereal *vol) const;
|
||||
|
||||
//@}
|
||||
/// @name Thermodynamic Values for the Species Reference States ---------------------
|
||||
//@{
|
||||
|
||||
|
||||
//! Returns the vector of nondimensional
|
||||
//! enthalpies of the reference state at the current temperature
|
||||
//! of the solution and the reference pressure for the species.
|
||||
/*!
|
||||
* @param hrt Output vector containing the nondimensional reference state
|
||||
* enthalpies. Length: m_kk.
|
||||
*/
|
||||
virtual void getEnthalpy_RT_ref(doublereal *hrt) const;
|
||||
|
||||
//! Returns the vector of nondimensional
|
||||
//! Gibbs Free Energies of the reference state at the current temperature
|
||||
//! of the solution and the reference pressure for the species.
|
||||
/*!
|
||||
* @param grt Output vector containing the nondimensional reference state
|
||||
* Gibbs Free energies. Length: m_kk.
|
||||
*/
|
||||
virtual void getGibbs_RT_ref(doublereal *grt) const;
|
||||
|
||||
//! Returns the vector of the
|
||||
//! gibbs function of the reference state at the current temperature
|
||||
//! of the solution and the reference pressure for the species.
|
||||
/*!
|
||||
* units = J/kmol
|
||||
*
|
||||
* @param g Output vector containing the reference state
|
||||
* Gibbs Free energies. Length: m_kk. Units: J/kmol.
|
||||
*/
|
||||
virtual void getGibbs_ref(doublereal *g) const;
|
||||
|
||||
//! Returns the vector of nondimensional
|
||||
//! entropies of the reference state at the current temperature
|
||||
//! of the solution and the reference pressure for each species.
|
||||
/*!
|
||||
* @param er Output vector containing the nondimensional reference state
|
||||
* entropies. Length: m_kk.
|
||||
*/
|
||||
virtual void getEntropy_R_ref(doublereal *er) const;
|
||||
|
||||
//! Returns the vector of nondimensional
|
||||
//! internal Energies of the reference state at the current temperature
|
||||
//! of the solution and the reference pressure for each species.
|
||||
/*!
|
||||
* @param urt Output vector of nondimensional reference state
|
||||
* internal energies of the species.
|
||||
* Length: m_kk
|
||||
*/
|
||||
virtual void getIntEnergy_RT_ref(doublereal *urt) const;
|
||||
|
||||
//! Returns the vector of nondimensional
|
||||
//! constant pressure heat capacities of the reference state
|
||||
//! at the current temperature of the solution
|
||||
//! and reference pressure for each species.
|
||||
/*!
|
||||
* @param cprt Output vector of nondimensional reference state
|
||||
* heat capacities at constant pressure for the species.
|
||||
* Length: m_kk
|
||||
*/
|
||||
virtual void getCp_R_ref(doublereal *cprt) const;
|
||||
|
||||
//! Get the molar volumes of the species standard states at the current
|
||||
//! <I>T</I> and <I>P_ref</I> of the solution.
|
||||
/*!
|
||||
* units = m^3 / kmol
|
||||
*
|
||||
* @param vol Output vector containing the standard state volumes.
|
||||
* Length: m_kk.
|
||||
*/
|
||||
virtual void getStandardVolumes_ref(doublereal *vol) const;
|
||||
|
||||
//@}
|
||||
/// @name NonVirtual Internal methods to Return References to Reference State Thermo
|
||||
//@{
|
||||
|
||||
//! Returns a reference to the dimensionless reference state enthalpy vector.
|
||||
/*!
|
||||
* This function is part of the layer that checks/recalculates the reference
|
||||
* state thermo functions.
|
||||
*/
|
||||
const array_fp& enthalpy_RT_ref() const {
|
||||
_updateThermo();
|
||||
return m_h0_RT;
|
||||
}
|
||||
|
||||
//! Returns a reference to the dimensionless reference state Gibbs free energy vector.
|
||||
/*!
|
||||
* This function is part of the layer that checks/recalculates the reference
|
||||
* state thermo functions.
|
||||
*/
|
||||
const array_fp& gibbs_RT_ref() const {
|
||||
_updateThermo();
|
||||
return m_g0_RT;
|
||||
}
|
||||
|
||||
//! Returns a reference to the exponent of the dimensionless reference state Gibbs Free energy vector.
|
||||
/*!
|
||||
* This function is part of the layer that checks/recalculates the reference
|
||||
* state thermo functions.
|
||||
*/
|
||||
const array_fp& expGibbs_RT_ref() const {
|
||||
_updateThermo();
|
||||
int k;
|
||||
for (k = 0; k != m_kk; k++) m_expg0_RT[k] = std::exp(m_g0_RT[k]);
|
||||
return m_expg0_RT;
|
||||
}
|
||||
|
||||
//! Returns a reference to the dimensionless reference state Entropy vector.
|
||||
/*!
|
||||
* This function is part of the layer that checks/recalculates the reference
|
||||
* state thermo functions.
|
||||
*/
|
||||
const array_fp& entropy_R_ref() const {
|
||||
_updateThermo();
|
||||
return m_s0_R;
|
||||
}
|
||||
|
||||
//! Returns a reference to the dimensionless reference state Heat Capacity vector.
|
||||
/*!
|
||||
* This function is part of the layer that checks/recalculates the reference
|
||||
* state thermo functions.
|
||||
*/
|
||||
const array_fp& cp_R_ref() const {
|
||||
_updateThermo();
|
||||
return m_cp0_R;
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
//! Initialize the ThermoPhase object after all species have been set up
|
||||
/*!
|
||||
* @internal Initialize.
|
||||
*
|
||||
* This method is provided to allow
|
||||
* subclasses to perform any initialization required after all
|
||||
* species have been added. For example, it might be used to
|
||||
* resize internal work arrays that must have an entry for
|
||||
* each species. The base class implementation does nothing,
|
||||
* and subclasses that do not require initialization do not
|
||||
* need to overload this method. When importing a CTML phase
|
||||
* description, this method is called from ThermoPhase::initThermoXML(),
|
||||
* which is called from importPhase(),
|
||||
* just prior to returning from function importPhase().
|
||||
*
|
||||
* @see importCTML.cpp
|
||||
*/
|
||||
virtual void initThermo();
|
||||
|
||||
//!This method is used by the ChemEquil equilibrium solver.
|
||||
/*!
|
||||
* @internal
|
||||
* @name Chemical Equilibrium
|
||||
* @{
|
||||
*
|
||||
* Set mixture to an equilibrium state consistent with specified
|
||||
* element potentials and temperature.
|
||||
* It sets the state such that the chemical potentials satisfy
|
||||
* \f[ \frac{\mu_k}{\hat R T} = \sum_m A_{k,m}
|
||||
* \left(\frac{\lambda_m} {\hat R T}\right) \f] where
|
||||
* \f$ \lambda_m \f$ is the element potential of element m. The
|
||||
* temperature is unchanged. Any phase (ideal or not) that
|
||||
* implements this method can be equilibrated by ChemEquil.
|
||||
*
|
||||
* @param lambda_RT vector of non-dimensional element potentials
|
||||
* \f[ \lambda_m/RT \f].
|
||||
*/
|
||||
virtual void setToEquilState(const doublereal* lambda_RT);
|
||||
|
||||
//@}
|
||||
|
||||
protected:
|
||||
|
||||
//! Number of Elements in the phase
|
||||
/*!
|
||||
* This member is defined here, from a call to the Elements ojbect, for speed.
|
||||
*/
|
||||
int m_mm;
|
||||
|
||||
//! Minimum temperature for valid species standard state thermo props
|
||||
/*!
|
||||
* This is the minimum temperature at which all species have valid standard
|
||||
* state thermo props defined.
|
||||
*/
|
||||
doublereal m_tmin;
|
||||
|
||||
//! Maximum temperature for valid species standard state thermo props
|
||||
/*!
|
||||
* This is the maximum temperature at which all species have valid standard
|
||||
* state thermo props defined.
|
||||
*/
|
||||
doublereal m_tmax;
|
||||
|
||||
//! Reference state pressure
|
||||
/*!
|
||||
* Value of the reference state pressure in Pascals.
|
||||
* All species must have the same reference state pressure.
|
||||
*/
|
||||
doublereal m_p0;
|
||||
|
||||
//! last value of the temperature processed by reference state
|
||||
mutable doublereal m_tlast;
|
||||
|
||||
//! Temporary storage for log of p/rt
|
||||
mutable doublereal m_logc0;
|
||||
|
||||
//! Temporary storage for dimensionless reference state enthalpies
|
||||
mutable array_fp m_h0_RT;
|
||||
|
||||
//! Temporary storage for dimensionless reference state heat capacities
|
||||
mutable array_fp m_cp0_R;
|
||||
|
||||
//! Temporary storage for dimensionless reference state gibbs energies
|
||||
mutable array_fp m_g0_RT;
|
||||
|
||||
//! Temporary storage for dimensionless reference state entropies
|
||||
mutable array_fp m_s0_R;
|
||||
|
||||
//! currently unsed
|
||||
/*!
|
||||
* @deprecated
|
||||
*/
|
||||
mutable array_fp m_expg0_RT;
|
||||
|
||||
//! Currently unused
|
||||
/*
|
||||
* @deprecated
|
||||
*/
|
||||
mutable array_fp m_pe;
|
||||
|
||||
//! Temporary array containing internally calculated partial pressures
|
||||
mutable array_fp m_pp;
|
||||
|
||||
private:
|
||||
|
||||
//! Update the species reference state thermodynamic functions
|
||||
/*!
|
||||
* The polynomials for the standard state functions are only
|
||||
* reevalulated if the temperature has changed.
|
||||
*
|
||||
*/
|
||||
void _updateThermo() const;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -25,7 +25,8 @@
|
|||
*/
|
||||
|
||||
#include "IdealMolalSoln.h"
|
||||
#include "importCTML.h"
|
||||
//#include "importCTML.h"
|
||||
#include "ThermoFactory.h"
|
||||
#include <math.h>
|
||||
|
||||
namespace Cantera {
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@
|
|||
|
||||
#include "mix_defs.h"
|
||||
#include "ThermoPhase.h"
|
||||
#include "importCTML.h"
|
||||
//#include "importCTML.h"
|
||||
#include "ThermoFactory.h"
|
||||
#include "SpeciesThermo.h"
|
||||
|
||||
|
||||
|
|
|
|||
129
Cantera/src/thermo/LatticePhase.cpp
Normal file
129
Cantera/src/thermo/LatticePhase.cpp
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
/**
|
||||
*
|
||||
* @file LatticePhase.cpp
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma warning(disable:4786)
|
||||
#pragma warning(disable:4503)
|
||||
#endif
|
||||
|
||||
#include "ct_defs.h"
|
||||
#include "mix_defs.h"
|
||||
#include "LatticePhase.h"
|
||||
#include "SpeciesThermo.h"
|
||||
#include <math.h>
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
doublereal LatticePhase::
|
||||
enthalpy_mole() const {
|
||||
doublereal p0 = m_spthermo->refPressure();
|
||||
return GasConstant * temperature() *
|
||||
mean_X(&enthalpy_RT()[0])
|
||||
+ (pressure() - p0)/molarDensity();
|
||||
}
|
||||
|
||||
doublereal LatticePhase::intEnergy_mole() const {
|
||||
doublereal p0 = m_spthermo->refPressure();
|
||||
return GasConstant * temperature() *
|
||||
mean_X(&enthalpy_RT()[0])
|
||||
- p0/molarDensity();
|
||||
}
|
||||
|
||||
doublereal LatticePhase::entropy_mole() const {
|
||||
return GasConstant * (mean_X(&entropy_R()[0]) -
|
||||
sum_xlogx());
|
||||
}
|
||||
|
||||
doublereal LatticePhase::gibbs_mole() const {
|
||||
return enthalpy_mole() - temperature() * entropy_mole();
|
||||
}
|
||||
|
||||
doublereal LatticePhase::cp_mole() const {
|
||||
return GasConstant * mean_X(&cp_R()[0]);
|
||||
}
|
||||
|
||||
void LatticePhase::getActivityConcentrations(doublereal* c) const {
|
||||
getMoleFractions(c);
|
||||
}
|
||||
|
||||
void LatticePhase::getActivityCoefficients(doublereal* ac) const {
|
||||
for (int k = 0; k < m_kk; k++) {
|
||||
ac[k] = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
doublereal LatticePhase::standardConcentration(int k) const {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
doublereal LatticePhase::logStandardConc(int k) const {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
void LatticePhase::getChemPotentials(doublereal* mu) const {
|
||||
doublereal vdp = (pressure() - m_spthermo->refPressure())/
|
||||
molarDensity();
|
||||
doublereal xx;
|
||||
doublereal rt = temperature() * GasConstant;
|
||||
const array_fp& g_RT = gibbs_RT();
|
||||
for (int k = 0; k < m_kk; k++) {
|
||||
xx = fmaxx(SmallNumber, moleFraction(k));
|
||||
mu[k] = rt*(g_RT[k] + log(xx)) + vdp;
|
||||
}
|
||||
}
|
||||
|
||||
void LatticePhase::getStandardChemPotentials(doublereal* mu0) const {
|
||||
const array_fp& gibbsrt = gibbs_RT();
|
||||
scale(gibbsrt.begin(), gibbsrt.end(), mu0, _RT());
|
||||
}
|
||||
|
||||
void LatticePhase::initThermo() {
|
||||
m_kk = nSpecies();
|
||||
m_mm = nElements();
|
||||
doublereal tmin = m_spthermo->minTemp();
|
||||
doublereal tmax = m_spthermo->maxTemp();
|
||||
if (tmin > 0.0) m_tmin = tmin;
|
||||
if (tmax > 0.0) m_tmax = tmax;
|
||||
m_p0 = refPressure();
|
||||
|
||||
int leng = m_kk;
|
||||
m_h0_RT.resize(leng);
|
||||
m_g0_RT.resize(leng);
|
||||
m_cp0_R.resize(leng);
|
||||
m_s0_R.resize(leng);
|
||||
setMolarDensity(m_molar_density);
|
||||
}
|
||||
|
||||
|
||||
void LatticePhase::_updateThermo() const {
|
||||
doublereal tnow = temperature();
|
||||
if (fabs(molarDensity() - m_molar_density)/m_molar_density > 0.0001) {
|
||||
throw CanteraError("_updateThermo","molar density changed from "
|
||||
+fp2str(m_molar_density)+" to "+fp2str(molarDensity()));
|
||||
}
|
||||
if (m_tlast != tnow) {
|
||||
m_spthermo->update(tnow, &m_cp0_R[0], &m_h0_RT[0],
|
||||
&m_s0_R[0]);
|
||||
m_tlast = tnow;
|
||||
int k;
|
||||
for (k = 0; k < m_kk; k++) {
|
||||
m_g0_RT[k] = m_h0_RT[k] - m_s0_R[k];
|
||||
}
|
||||
m_tlast = tnow;
|
||||
}
|
||||
}
|
||||
|
||||
void LatticePhase::setParametersFromXML(const XML_Node& eosdata) {
|
||||
eosdata._require("model","Lattice");
|
||||
m_molar_density = getFloat(eosdata, "site_density", "-");
|
||||
m_vacancy = getString(eosdata, "vacancy_species");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
150
Cantera/src/thermo/LatticePhase.h
Normal file
150
Cantera/src/thermo/LatticePhase.h
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
/**
|
||||
*
|
||||
* @file LatticePhase.h
|
||||
*/
|
||||
|
||||
/* $Author$
|
||||
* $Date$
|
||||
* $Revision$
|
||||
*
|
||||
* Copyright 2005 California Institute of Technology
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CT_LATTICE_H
|
||||
#define CT_LATTICE_H
|
||||
|
||||
#include "ct_defs.h"
|
||||
#include "mix_defs.h"
|
||||
#include "ThermoPhase.h"
|
||||
#include "SpeciesThermo.h"
|
||||
#include "utilities.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
/**
|
||||
*/
|
||||
class LatticePhase : public ThermoPhase {
|
||||
|
||||
public:
|
||||
|
||||
LatticePhase() : m_tlast(0.0) {}
|
||||
|
||||
virtual ~LatticePhase() {}
|
||||
|
||||
virtual int eosType() const { return cLattice; }
|
||||
|
||||
virtual doublereal enthalpy_mole() const;
|
||||
|
||||
virtual doublereal intEnergy_mole() const;
|
||||
|
||||
virtual doublereal entropy_mole() const;
|
||||
|
||||
virtual doublereal gibbs_mole() const;
|
||||
|
||||
virtual doublereal cp_mole() const;
|
||||
|
||||
virtual doublereal cv_mole() const {
|
||||
return cp_mole();
|
||||
}
|
||||
|
||||
virtual doublereal pressure() const {
|
||||
return m_press;
|
||||
}
|
||||
|
||||
virtual void setPressure(doublereal p) {
|
||||
m_press = p;
|
||||
setMolarDensity(m_molar_density);
|
||||
}
|
||||
|
||||
virtual void getActivityConcentrations(doublereal* c) const;
|
||||
|
||||
virtual void getActivityCoefficients(doublereal* ac) const;
|
||||
|
||||
virtual void getChemPotentials(doublereal* mu) const;
|
||||
virtual void getStandardChemPotentials(doublereal* mu0) const;
|
||||
virtual doublereal standardConcentration(int k=0) const;
|
||||
virtual doublereal logStandardConc(int k=0) const;
|
||||
|
||||
virtual void getPureGibbs(doublereal* gpure) const {
|
||||
const array_fp& gibbsrt = gibbs_RT();
|
||||
scale(gibbsrt.begin(), gibbsrt.end(), gpure, _RT());
|
||||
}
|
||||
|
||||
void getEnthalpy_RT(doublereal* hrt) const {
|
||||
const array_fp& _h = enthalpy_RT();
|
||||
std::copy(_h.begin(), _h.end(), hrt);
|
||||
}
|
||||
|
||||
void getEntropy_R(doublereal* sr) const {
|
||||
const array_fp& _s = entropy_R();
|
||||
std::copy(_s.begin(), _s.end(), sr);
|
||||
}
|
||||
|
||||
virtual void getGibbs_RT(doublereal* grt) const {
|
||||
const array_fp& gibbsrt = gibbs_RT();
|
||||
std::copy(gibbsrt.begin(), gibbsrt.end(), grt);
|
||||
}
|
||||
|
||||
void getCp_R(doublereal* cpr) const {
|
||||
const array_fp& _cpr = cp_R();
|
||||
std::copy(_cpr.begin(), _cpr.end(), cpr);
|
||||
}
|
||||
|
||||
|
||||
// new methods defined here
|
||||
|
||||
const array_fp& enthalpy_RT() const {
|
||||
_updateThermo();
|
||||
return m_h0_RT;
|
||||
}
|
||||
|
||||
const array_fp& gibbs_RT() const {
|
||||
_updateThermo();
|
||||
return m_g0_RT;
|
||||
}
|
||||
|
||||
const array_fp& entropy_R() const {
|
||||
_updateThermo();
|
||||
return m_s0_R;
|
||||
}
|
||||
|
||||
const array_fp& cp_R() const {
|
||||
_updateThermo();
|
||||
return m_cp0_R;
|
||||
}
|
||||
|
||||
virtual void initThermo();
|
||||
|
||||
// set the site density of sublattice n
|
||||
virtual void setParameters(int n, doublereal* c) {}
|
||||
|
||||
virtual void getParameters(int &n, doublereal * const c) {
|
||||
double d = molarDensity();
|
||||
c[0] = d;
|
||||
n = 1;
|
||||
}
|
||||
|
||||
virtual void setParametersFromXML(const XML_Node& eosdata);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
int m_mm;
|
||||
doublereal m_tmin, m_tmax, m_p0;
|
||||
mutable doublereal m_tlast;
|
||||
mutable array_fp m_h0_RT;
|
||||
mutable array_fp m_cp0_R;
|
||||
mutable array_fp m_g0_RT;
|
||||
mutable array_fp m_s0_R;
|
||||
doublereal m_press;
|
||||
std::string m_vacancy;
|
||||
doublereal m_molar_density;
|
||||
|
||||
private:
|
||||
|
||||
void _updateThermo() const;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
235
Cantera/src/thermo/LatticeSolidPhase.cpp
Normal file
235
Cantera/src/thermo/LatticeSolidPhase.cpp
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
/**
|
||||
*
|
||||
* @file LatticeSolidPhase.cpp
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma warning(disable:4786)
|
||||
#pragma warning(disable:4503)
|
||||
#endif
|
||||
|
||||
#include "ct_defs.h"
|
||||
#include "mix_defs.h"
|
||||
#include "LatticeSolidPhase.h"
|
||||
#include "LatticePhase.h"
|
||||
#include "SpeciesThermo.h"
|
||||
#include "ThermoFactory.h"
|
||||
//#include "importCTML.h"
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
doublereal LatticeSolidPhase::
|
||||
enthalpy_mole() const {
|
||||
_updateThermo();
|
||||
doublereal ndens, sum = 0.0;
|
||||
int n;
|
||||
for (n = 0; n < m_nlattice; n++) {
|
||||
ndens = m_lattice[n]->molarDensity();
|
||||
sum += ndens * m_lattice[n]->enthalpy_mole();
|
||||
}
|
||||
return sum/molarDensity();
|
||||
}
|
||||
|
||||
doublereal LatticeSolidPhase::intEnergy_mole() const {
|
||||
_updateThermo();
|
||||
doublereal ndens, sum = 0.0;
|
||||
int n;
|
||||
for (n = 0; n < m_nlattice; n++) {
|
||||
ndens = m_lattice[n]->molarDensity();
|
||||
sum += ndens * m_lattice[n]->intEnergy_mole();
|
||||
}
|
||||
return sum/molarDensity();
|
||||
}
|
||||
|
||||
doublereal LatticeSolidPhase::entropy_mole() const {
|
||||
_updateThermo();
|
||||
doublereal ndens, sum = 0.0;
|
||||
int n;
|
||||
for (n = 0; n < m_nlattice; n++) {
|
||||
ndens = m_lattice[n]->molarDensity();
|
||||
sum += ndens * m_lattice[n]->entropy_mole();
|
||||
}
|
||||
return sum/molarDensity();
|
||||
}
|
||||
|
||||
doublereal LatticeSolidPhase::gibbs_mole() const {
|
||||
_updateThermo();
|
||||
doublereal ndens, sum = 0.0;
|
||||
int n;
|
||||
for (n = 0; n < m_nlattice; n++) {
|
||||
ndens = m_lattice[n]->molarDensity();
|
||||
sum += ndens * m_lattice[n]->gibbs_mole();
|
||||
}
|
||||
return sum/molarDensity();
|
||||
}
|
||||
|
||||
doublereal LatticeSolidPhase::cp_mole() const {
|
||||
_updateThermo();
|
||||
doublereal ndens, sum = 0.0;
|
||||
int n;
|
||||
for (n = 0; n < m_nlattice; n++) {
|
||||
ndens = m_lattice[n]->molarDensity();
|
||||
sum += ndens * m_lattice[n]->cp_mole();
|
||||
}
|
||||
return sum/molarDensity();
|
||||
}
|
||||
|
||||
void LatticeSolidPhase::getActivityConcentrations(doublereal* c) const {
|
||||
_updateThermo();
|
||||
int n;
|
||||
int strt = 0;
|
||||
for (n = 0; n < m_nlattice; n++) {
|
||||
m_lattice[n]->getMoleFractions(c+strt);
|
||||
strt += m_lattice[n]->nSpecies();
|
||||
}
|
||||
}
|
||||
|
||||
void LatticeSolidPhase::getActivityCoefficients(doublereal* ac) const {
|
||||
for (int k = 0; k < m_kk; k++) {
|
||||
ac[k] = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
doublereal LatticeSolidPhase::standardConcentration(int k) const {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
doublereal LatticeSolidPhase::logStandardConc(int k) const {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
void LatticeSolidPhase::getChemPotentials(doublereal* mu) const {
|
||||
_updateThermo();
|
||||
int n;
|
||||
int strt = 0;
|
||||
double dratio;
|
||||
for (n = 0; n < m_nlattice; n++) {
|
||||
dratio = m_lattice[n]->molarDensity()/molarDensity();
|
||||
m_lattice[n]->getChemPotentials(mu+strt);
|
||||
scale(mu + strt, mu + strt + m_lattice[n]->nSpecies(), mu + strt, dratio);
|
||||
strt += m_lattice[n]->nSpecies();
|
||||
}
|
||||
}
|
||||
|
||||
void LatticeSolidPhase::getStandardChemPotentials(doublereal* mu0) const {
|
||||
_updateThermo();
|
||||
int n;
|
||||
int strt = 0;
|
||||
double dratio;
|
||||
for (n = 0; n < m_nlattice; n++) {
|
||||
dratio = m_lattice[n]->molarDensity()/molarDensity();
|
||||
m_lattice[n]->getStandardChemPotentials(mu0+strt);
|
||||
scale(mu0 + strt, mu0 + strt + m_lattice[n]->nSpecies(), mu0 + strt, dratio);
|
||||
strt += m_lattice[n]->nSpecies();
|
||||
}
|
||||
}
|
||||
|
||||
void LatticeSolidPhase::initThermo() {
|
||||
m_kk = nSpecies();
|
||||
m_mm = nElements();
|
||||
m_x.resize(m_kk);
|
||||
int n, nsp, k, loc = 0;
|
||||
doublereal ndens;
|
||||
m_molar_density = 0.0;
|
||||
for (n = 0; n < m_nlattice; n++) {
|
||||
nsp = m_lattice[n]->nSpecies();
|
||||
ndens = m_lattice[n]->molarDensity();
|
||||
for (k = 0; k < nsp; k++) {
|
||||
m_x[loc] = ndens * m_lattice[n]->moleFraction(k);
|
||||
loc++;
|
||||
}
|
||||
m_molar_density += ndens;
|
||||
}
|
||||
setMoleFractions(DATA_PTR(m_x));
|
||||
|
||||
// const vector<string>& spnames = speciesNames();
|
||||
// int n, k, kl, namesize;
|
||||
// int nl = m_sitedens.size();
|
||||
// string s;
|
||||
// m_lattice.resize(m_kk,-1);
|
||||
// vector_fp conc(m_kk, 0.0);
|
||||
|
||||
// compositionMap xx;
|
||||
// for (n = 0; n < nl; n++) {
|
||||
// for (k = 0; k < m_kk; k++) {
|
||||
// xx[speciesName(k)] = -1.0;
|
||||
// }
|
||||
// parseCompString(m_sp[n], xx);
|
||||
// for (k = 0; k < m_kk; k++) {
|
||||
// if (xx[speciesName(k)] != -1.0) {
|
||||
// conc[k] = m_sitedens[n]*xx[speciesName(k)];
|
||||
// m_lattice[k] = n;
|
||||
// }
|
||||
// }
|
||||
|
||||
// }
|
||||
// for (k = 0; k < m_kk; k++) {
|
||||
// if (m_lattice[k] == -1) {
|
||||
// throw CanteraError("LatticeSolidPhase::"
|
||||
// "setParametersFromXML","Species "+speciesName(k)
|
||||
// +" not a member of any lattice.");
|
||||
// }
|
||||
// }
|
||||
// setMoleFractions(DATA_PTR(conc));
|
||||
}
|
||||
|
||||
|
||||
void LatticeSolidPhase::_updateThermo() const {
|
||||
doublereal tnow = temperature();
|
||||
// if (fabs(molarDensity() - m_molar_density)/m_molar_density > 0.0001) {
|
||||
// throw CanteraError("_updateThermo","molar density changed from "
|
||||
// +fp2str(m_molar_density)+" to "+fp2str(molarDensity()));
|
||||
//}
|
||||
if (m_tlast != tnow) {
|
||||
int n;
|
||||
getMoleFractions(DATA_PTR(m_x));
|
||||
int strt = 0;
|
||||
for (n = 0; n < m_nlattice; n++) {
|
||||
m_lattice[n]->setTemperature(tnow);
|
||||
m_lattice[n]->setMoleFractions(DATA_PTR(m_x) + strt);
|
||||
m_lattice[n]->setPressure(m_press);
|
||||
strt += m_lattice[n]->nSpecies();
|
||||
}
|
||||
m_tlast = tnow;
|
||||
}
|
||||
}
|
||||
|
||||
void LatticeSolidPhase::setLatticeMoleFractions(int nn,
|
||||
string x) {
|
||||
m_lattice[nn]->setMoleFractionsByName(x);
|
||||
int n, k, loc=0, nsp;
|
||||
doublereal ndens;
|
||||
for (n = 0; n < m_nlattice; n++) {
|
||||
nsp = m_lattice[n]->nSpecies();
|
||||
ndens = m_lattice[n]->molarDensity();
|
||||
for (k = 0; k < nsp; k++) {
|
||||
m_x[loc] = ndens * m_lattice[n]->moleFraction(k);
|
||||
loc++;
|
||||
}
|
||||
}
|
||||
setMoleFractions(DATA_PTR(m_x));
|
||||
}
|
||||
|
||||
void LatticeSolidPhase::setParametersFromXML(const XML_Node& eosdata) {
|
||||
eosdata._require("model","LatticeSolid");
|
||||
XML_Node& la = eosdata.child("LatticeArray");
|
||||
vector<XML_Node*> lattices;
|
||||
la.getChildren("phase",lattices);
|
||||
int n;
|
||||
int nl = lattices.size();
|
||||
m_nlattice = nl;
|
||||
for (n = 0; n < nl; n++) {
|
||||
XML_Node& i = *lattices[n];
|
||||
m_lattice.push_back((LatticePhase*)newPhase(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
92
Cantera/src/thermo/LatticeSolidPhase.h
Normal file
92
Cantera/src/thermo/LatticeSolidPhase.h
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
/**
|
||||
*
|
||||
* @file LatticeSolidPhase.h
|
||||
*/
|
||||
|
||||
/* $Author$
|
||||
* $Date$
|
||||
* $Revision$
|
||||
*
|
||||
* Copyright 2005 California Institute of Technology
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CT_LATTICESOLID_H
|
||||
#define CT_LATTICESOLID_H
|
||||
|
||||
#include "ct_defs.h"
|
||||
#include "mix_defs.h"
|
||||
#include "ThermoPhase.h"
|
||||
#include "SpeciesThermo.h"
|
||||
#include "utilities.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
class LatticePhase;
|
||||
|
||||
class LatticeSolidPhase : public ThermoPhase {
|
||||
|
||||
public:
|
||||
|
||||
LatticeSolidPhase() : m_tlast(0.0) {}
|
||||
|
||||
virtual ~LatticeSolidPhase() {}
|
||||
|
||||
virtual int eosType() const { return cLatticeSolid; }
|
||||
|
||||
virtual doublereal enthalpy_mole() const;
|
||||
|
||||
virtual doublereal intEnergy_mole() const;
|
||||
|
||||
virtual doublereal entropy_mole() const;
|
||||
|
||||
virtual doublereal gibbs_mole() const;
|
||||
|
||||
virtual doublereal cp_mole() const;
|
||||
|
||||
virtual doublereal cv_mole() const {
|
||||
return cp_mole();
|
||||
}
|
||||
|
||||
virtual doublereal pressure() const {
|
||||
return m_press;
|
||||
}
|
||||
|
||||
virtual void setPressure(doublereal p) {
|
||||
m_press = p;
|
||||
setMolarDensity(m_molar_density);
|
||||
}
|
||||
|
||||
virtual void getActivityConcentrations(doublereal* c) const;
|
||||
|
||||
virtual void getActivityCoefficients(doublereal* ac) const;
|
||||
|
||||
virtual void getChemPotentials(doublereal* mu) const;
|
||||
virtual void getStandardChemPotentials(doublereal* mu0) const;
|
||||
virtual doublereal standardConcentration(int k=0) const;
|
||||
virtual doublereal logStandardConc(int k=0) const;
|
||||
|
||||
virtual void initThermo();
|
||||
|
||||
virtual void setParametersFromXML(const XML_Node& eosdata);
|
||||
|
||||
void setLatticeMoleFractions(int n, std::string x);
|
||||
|
||||
protected:
|
||||
|
||||
int m_mm;
|
||||
int m_kk;
|
||||
mutable doublereal m_tlast;
|
||||
doublereal m_press;
|
||||
doublereal m_molar_density;
|
||||
int m_nlattice;
|
||||
std::vector<LatticePhase*> m_lattice;
|
||||
mutable vector_fp m_x;
|
||||
|
||||
private:
|
||||
|
||||
void _updateThermo() const;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
.SUFFIXES :
|
||||
.SUFFIXES : .cpp .d .o .h
|
||||
|
||||
INCDIR = ../../../build/include/cantera/kernel/thermo
|
||||
INCDIR = ../../../build/include/cantera/kernel
|
||||
INSTALL_TSC = ../../../bin/install_tsc
|
||||
do_ranlib = @DO_RANLIB@
|
||||
do_electro = @COMPILE_ELECTROLYTES@
|
||||
|
|
@ -29,6 +29,26 @@ PIC_FLAG=@PIC@
|
|||
|
||||
CXX_FLAGS = @CXXFLAGS@ $(LOCAL_DEFS) $(CXX_OPT) $(PIC_FLAG) $(DEBUG_FLAG)
|
||||
|
||||
# Basic Cantera Thermodynamics Object Files
|
||||
THERMO_OBJ = State.o Elements.o Constituents.o Phase.o \
|
||||
ThermoPhase.o IdealGasPhase.o ConstDensityThermo.o \
|
||||
SpeciesThermoFactory.o ConstCpPoly.o \
|
||||
Mu0Poly.o GeneralSpeciesThermo.o SurfPhase.o \
|
||||
ThermoFactory.o phasereport.o @phase_object_files@
|
||||
|
||||
THERMO_H = State.h Elements.h Constituents.h Phase.h mix_defs.h \
|
||||
ThermoPhase.h IdealGasPhase.h ConstDensityThermo.h \
|
||||
SpeciesThermoFactory.h ThermoFactory.h \
|
||||
NasaPoly1.h NasaPoly2.h NasaThermo.h \
|
||||
ShomateThermo.h ShomatePoly.h ConstCpPoly.h \
|
||||
SimpleThermo.h SpeciesThermoMgr.h \
|
||||
SpeciesThermoInterpType.h \
|
||||
GeneralSpeciesThermo.h Mu0Poly.h \
|
||||
speciesThermoTypes.h SpeciesThermo.h SurfPhase.h \
|
||||
EdgePhase.h \
|
||||
@phase_header_files@
|
||||
|
||||
|
||||
# Extended Cantera Thermodynamics Object Files
|
||||
|
||||
ifeq ($(do_electro),1)
|
||||
|
|
@ -51,13 +71,13 @@ ISSP_OBJ = IdealSolidSolnPhase.o StoichSubstanceSSTP.o SingleSpeciesTP.o
|
|||
ISSP_H = IdealSolidSolnPhase.h StoichSubstanceSSTP.h SingleSpeciesTP.h
|
||||
endif
|
||||
|
||||
CATHERMO_OBJ = $(ELECTRO_OBJ) $(ISSP_OBJ)
|
||||
CATHERMO_OBJ = $(THERMO_OBJ) $(ELECTRO_OBJ) $(ISSP_OBJ)
|
||||
|
||||
CATHERMO_H = $(ELECTRO_H) $(ISSP_H)
|
||||
CATHERMO_H = $(THERMO_H) $(ELECTRO_H) $(ISSP_H)
|
||||
|
||||
|
||||
CXX_INCLUDES = -I.. @CXX_INCLUDES@
|
||||
LIB = @buildlib@/libcaThermo.a
|
||||
CXX_INCLUDES = -I../base @CXX_INCLUDES@
|
||||
LIB = @buildlib@/libthermo.a
|
||||
|
||||
DEPENDS = $(CATHERMO_OBJ:.o=.d)
|
||||
|
||||
|
|
|
|||
95
Cantera/src/thermo/MetalPhase.h
Normal file
95
Cantera/src/thermo/MetalPhase.h
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
/**
|
||||
*
|
||||
* @file MetalPhase.h
|
||||
*
|
||||
*/
|
||||
|
||||
/* $Author$
|
||||
* $Date$
|
||||
* $Revision$
|
||||
*
|
||||
* Copyright 2003 California Institute of Technology
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CT_METALPHASE_H
|
||||
#define CT_METALPHASE_H
|
||||
|
||||
|
||||
#include "mix_defs.h"
|
||||
#include "ThermoPhase.h"
|
||||
#include "SpeciesThermo.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
/**
|
||||
* @ingroup thermoprops
|
||||
*
|
||||
* Class MetalPhase represents electrons in a metal.
|
||||
*
|
||||
*/
|
||||
class MetalPhase : public ThermoPhase {
|
||||
|
||||
public:
|
||||
|
||||
MetalPhase() {}
|
||||
|
||||
virtual ~MetalPhase() {}
|
||||
|
||||
// Overloaded methoods of class ThermoPhase
|
||||
|
||||
virtual int eosType() const { return cMetal; }
|
||||
|
||||
virtual doublereal enthalpy_mole() const { return 0.0; }
|
||||
virtual doublereal intEnergy_mole() const { return 0.0; }
|
||||
virtual doublereal entropy_mole() const { return 0.0; }
|
||||
virtual doublereal gibbs_mole() const { return 0.0; }
|
||||
virtual doublereal cp_mole() const { return 0.0; }
|
||||
virtual doublereal cv_mole() const { return 0.0; }
|
||||
|
||||
virtual void setPressure(doublereal pres) { m_press = pres; }
|
||||
virtual doublereal pressure() const { return m_press; }
|
||||
|
||||
virtual void getChemPotentials(doublereal* mu) const {
|
||||
int n, nsp = nSpecies();
|
||||
for (n = 0; n < nsp; n++) mu[n] = 0.0;
|
||||
}
|
||||
|
||||
virtual void getStandardChemPotentials(doublereal* mu0) const {
|
||||
int n, nsp = nSpecies();
|
||||
for (n = 0; n < nsp; n++) mu0[n] = 0.0;
|
||||
}
|
||||
|
||||
virtual void getActivityConcentrations(doublereal* c) const {
|
||||
int n, nsp = nSpecies();
|
||||
for (n = 0; n < nsp; n++) c[n] = 1.0;
|
||||
}
|
||||
|
||||
virtual doublereal standardConcentration(int k=0) const {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
virtual doublereal logStandardConc(int k=0) const {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
virtual void setParametersFromXML(const XML_Node& eosdata) {
|
||||
eosdata._require("model","Metal");
|
||||
doublereal rho = getFloat(eosdata, "density", "-");
|
||||
setDensity(rho);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
doublereal m_press;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
414
Cantera/src/thermo/Mu0Poly.cpp
Normal file
414
Cantera/src/thermo/Mu0Poly.cpp
Normal file
|
|
@ -0,0 +1,414 @@
|
|||
/**
|
||||
* @file Mu0Poly.cpp
|
||||
* Definitions for a single-species standard state object derived
|
||||
* from \link Cantera::SpeciesThermoInterpType SpeciesThermoInterpType\endlink based
|
||||
* on a piecewise constant mu0 interpolation
|
||||
* (see \ref spthermo and class \link Cantera::Mu0Poly Mu0Poly\endlink).
|
||||
*/
|
||||
/*
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
|
||||
#include "Mu0Poly.h"
|
||||
#include "ctexceptions.h"
|
||||
#include "speciesThermoTypes.h"
|
||||
#include "SpeciesThermo.h"
|
||||
#include "xml.h"
|
||||
#include "ctml.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace ctml;
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
|
||||
Mu0Poly::Mu0Poly() : m_numIntervals(0),
|
||||
m_H298(0.0),
|
||||
m_lowT(0.0),
|
||||
m_highT(0.0),
|
||||
m_Pref(0.0),
|
||||
m_index(0) {
|
||||
}
|
||||
|
||||
/*
|
||||
* Mu0Poly():
|
||||
*
|
||||
* In the constructor, we calculate and store the
|
||||
* piecewise linear approximation to the thermodynamic
|
||||
* functions.
|
||||
*
|
||||
* coeffs[0] = number of points (integer)
|
||||
* 1 = H298(J/kmol)
|
||||
* 2 = T1 (Kelvin)
|
||||
* 3 = mu1 (J/kmol)
|
||||
* 4 = T2 (Kelvin)
|
||||
* 5 = mu2 (J/kmol)
|
||||
* 6 = T3 (Kelvin)
|
||||
* 7 = mu3 (J/kmol)
|
||||
* ........
|
||||
*/
|
||||
Mu0Poly::Mu0Poly(int n, doublereal tlow, doublereal thigh,
|
||||
doublereal pref,
|
||||
const doublereal* coeffs) :
|
||||
m_numIntervals(0),
|
||||
m_H298(0.0),
|
||||
m_lowT (tlow),
|
||||
m_highT (thigh),
|
||||
m_Pref (pref),
|
||||
m_index (n) {
|
||||
|
||||
processCoeffs(coeffs);
|
||||
}
|
||||
|
||||
|
||||
Mu0Poly::Mu0Poly(const Mu0Poly &b)
|
||||
: m_numIntervals (b.m_numIntervals),
|
||||
m_H298 (b.m_H298),
|
||||
m_t0_int (b.m_t0_int),
|
||||
m_mu0_R_int (b.m_mu0_R_int),
|
||||
m_h0_R_int (b.m_h0_R_int),
|
||||
m_s0_R_int (b.m_s0_R_int),
|
||||
m_cp0_R_int (b.m_cp0_R_int),
|
||||
m_lowT (b.m_lowT),
|
||||
m_highT (b.m_highT),
|
||||
m_Pref (b.m_Pref),
|
||||
m_index (b.m_index) {
|
||||
}
|
||||
|
||||
Mu0Poly& Mu0Poly::operator=(const Mu0Poly& b) {
|
||||
if (&b != this) {
|
||||
m_numIntervals = b.m_numIntervals;
|
||||
m_H298 = b.m_H298;
|
||||
m_t0_int = b.m_t0_int;
|
||||
m_mu0_R_int = b.m_mu0_R_int;
|
||||
m_h0_R_int = b.m_h0_R_int;
|
||||
m_s0_R_int = b.m_s0_R_int;
|
||||
m_cp0_R_int = b.m_cp0_R_int;
|
||||
m_lowT = b.m_lowT;
|
||||
m_highT = b.m_highT;
|
||||
m_Pref = b.m_Pref;
|
||||
m_index = b.m_index;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor:
|
||||
*/
|
||||
Mu0Poly::~Mu0Poly(){
|
||||
}
|
||||
|
||||
SpeciesThermoInterpType *
|
||||
Mu0Poly::duplMyselfAsSpeciesThermoInterpType() const {
|
||||
Mu0Poly* mp = new Mu0Poly(*this);
|
||||
return (SpeciesThermoInterpType *) mp;
|
||||
}
|
||||
|
||||
doublereal Mu0Poly::minTemp() const { return m_lowT;}
|
||||
doublereal Mu0Poly::maxTemp() const { return m_highT;}
|
||||
doublereal Mu0Poly::refPressure() const { return m_Pref; }
|
||||
|
||||
/**
|
||||
* updateProperties is the main workhorse program.
|
||||
* Given a temperature (*tt), it calculates the thermodynamic
|
||||
* functions H/RT, S_R, and cp_R, and returns the answer.
|
||||
*
|
||||
* Note, it returns an answer by inserting the values into the
|
||||
* index position, m_index in vectors of H/RT, S_R, and cp_R.
|
||||
*
|
||||
*
|
||||
* Input
|
||||
* -------
|
||||
* *tt = Temperature (Kelvin)
|
||||
*
|
||||
*/
|
||||
void Mu0Poly::
|
||||
updateProperties(const doublereal* tt, doublereal* cp_R,
|
||||
doublereal* h_RT, doublereal* s_R) const {
|
||||
int j = m_numIntervals;
|
||||
double T = *tt;
|
||||
for (int i = 0; i < m_numIntervals; i++) {
|
||||
double T2 = m_t0_int[i+1];
|
||||
if (T <=T2) {
|
||||
j = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
double T1 = m_t0_int[j];
|
||||
double cp_Rj = m_cp0_R_int[j];
|
||||
|
||||
doublereal rt = 1.0/T;
|
||||
cp_R[m_index] = cp_Rj;
|
||||
h_RT[m_index] = rt*(m_h0_R_int[j] + (T - T1) * cp_Rj);
|
||||
s_R[m_index] = m_s0_R_int[j] + cp_Rj * (log(T/T1));
|
||||
}
|
||||
|
||||
void Mu0Poly::
|
||||
updatePropertiesTemp(const doublereal T,
|
||||
doublereal* cp_R,
|
||||
doublereal* h_RT,
|
||||
doublereal* s_R) const {
|
||||
updateProperties(&T, cp_R, h_RT, s_R);
|
||||
}
|
||||
|
||||
/*
|
||||
* report all of the parameters that make up this
|
||||
* interpolation.
|
||||
*
|
||||
*
|
||||
*/
|
||||
void Mu0Poly::reportParameters(int &n, int &type,
|
||||
doublereal &tlow, doublereal &thigh,
|
||||
doublereal &pref,
|
||||
doublereal* const coeffs) const {
|
||||
n = m_index;
|
||||
type = MU0_INTERP;
|
||||
tlow = m_lowT;
|
||||
thigh = m_highT;
|
||||
pref = m_Pref;
|
||||
coeffs[0] = m_numIntervals+1;
|
||||
coeffs[1] = m_H298 * GasConstant;
|
||||
int j = 2;
|
||||
for (int i = 0; i < m_numIntervals+1; i++) {
|
||||
coeffs[j] = m_t0_int[i];
|
||||
coeffs[j+1] = m_mu0_R_int[i] * GasConstant;
|
||||
j += 2;
|
||||
}
|
||||
}
|
||||
|
||||
void Mu0Poly::modifyParameters(doublereal* coeffs) {
|
||||
processCoeffs(coeffs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Install a Mu0 polynomial thermodynamic reference state property
|
||||
* parameterization for species k into a SpeciesThermo instance,
|
||||
* getting the information from an XML database.
|
||||
*/
|
||||
void installMu0ThermoFromXML(std::string speciesName,
|
||||
SpeciesThermo& sp, int k,
|
||||
const XML_Node* Mu0Node_ptr) {
|
||||
|
||||
doublereal tmin, tmax;
|
||||
bool dimensionlessMu0Values = false;
|
||||
const XML_Node& Mu0Node = *Mu0Node_ptr;
|
||||
|
||||
tmin = fpValue(Mu0Node["Tmin"]);
|
||||
tmax = fpValue(Mu0Node["Tmax"]);
|
||||
doublereal pref = fpValue(Mu0Node["Pref"]);
|
||||
|
||||
doublereal h298 = 0.0;
|
||||
if (Mu0Node.hasChild("H298")) {
|
||||
h298 = getFloat(Mu0Node, "H298", "actEnergy");
|
||||
}
|
||||
|
||||
int numPoints = 1;
|
||||
if (Mu0Node.hasChild("numPoints")) {
|
||||
numPoints = getInteger(Mu0Node, "numPoints");
|
||||
}
|
||||
|
||||
vector_fp cValues(numPoints);
|
||||
const XML_Node *valNode_ptr =
|
||||
getByTitle(const_cast<XML_Node&>(Mu0Node), "Mu0Values");
|
||||
if (!valNode_ptr) {
|
||||
throw CanteraError("installMu0ThermoFromXML",
|
||||
"missing required while processing "
|
||||
+ speciesName);
|
||||
}
|
||||
getFloatArray(*valNode_ptr, cValues, true, "actEnergy");
|
||||
/*
|
||||
* Check to see whether the Mu0's were input in a dimensionless
|
||||
* form. If they were, then the assumed temperature needs to be
|
||||
* adjusted from the assumed T = 273.15
|
||||
*/
|
||||
string uuu = (*valNode_ptr)["units"];
|
||||
if (uuu == "Dimensionless") {
|
||||
dimensionlessMu0Values = true;
|
||||
}
|
||||
int ns = cValues.size();
|
||||
if (ns != numPoints) {
|
||||
throw CanteraError("installMu0ThermoFromXML",
|
||||
"numPoints inconsistent while processing "
|
||||
+ speciesName);
|
||||
}
|
||||
|
||||
vector_fp cTemperatures(numPoints);
|
||||
const XML_Node *tempNode_ptr =
|
||||
getByTitle(const_cast<XML_Node&>(Mu0Node), "Mu0Temperatures");
|
||||
if (!tempNode_ptr) {
|
||||
throw CanteraError("installMu0ThermoFromXML",
|
||||
"missing required while processing + "
|
||||
+ speciesName);
|
||||
}
|
||||
getFloatArray(*tempNode_ptr, cTemperatures, false);
|
||||
ns = cTemperatures.size();
|
||||
if (ns != numPoints) {
|
||||
throw CanteraError("installMu0ThermoFromXML",
|
||||
"numPoints inconsistent while processing "
|
||||
+ speciesName);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fix up dimensionless Mu0 values if input
|
||||
*/
|
||||
if (dimensionlessMu0Values) {
|
||||
for (int i = 0; i < numPoints; i++) {
|
||||
cValues[i] *= cTemperatures[i] / 273.15;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
vector_fp c(2 + 2 * numPoints);
|
||||
|
||||
c[0] = numPoints;
|
||||
c[1] = h298;
|
||||
for (int i = 0; i < numPoints; i++) {
|
||||
c[2+i*2] = cTemperatures[i];
|
||||
c[2+i*2+1] = cValues[i];
|
||||
}
|
||||
|
||||
sp.install(speciesName, k, MU0_INTERP, &c[0], tmin, tmax, pref);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mu0Poly():
|
||||
*
|
||||
* In the constructor, we calculate and store the
|
||||
* piecewise linear approximation to the thermodynamic
|
||||
* functions.
|
||||
*
|
||||
* coeffs[0] = number of points (integer)
|
||||
* 1 = H298(J/kmol)
|
||||
* 2 = T1 (Kelvin)
|
||||
* 3 = mu1 (J/kmol)
|
||||
* 4 = T2 (Kelvin)
|
||||
* 5 = mu2 (J/kmol)
|
||||
* 6 = T3 (Kelvin)
|
||||
* 7 = mu3 (J/kmol)
|
||||
* ........
|
||||
*/
|
||||
void Mu0Poly::processCoeffs(const doublereal* coeffs) {
|
||||
|
||||
int i, iindex;
|
||||
double T1, T2;
|
||||
int nPoints = (int) coeffs[0];
|
||||
if (nPoints < 2) {
|
||||
throw CanteraError("Mu0Poly",
|
||||
"nPoints must be >= 2");
|
||||
}
|
||||
m_numIntervals = nPoints - 1;
|
||||
m_H298 = coeffs[1] / GasConstant;
|
||||
int iT298 = 0;
|
||||
/*
|
||||
* Resize according to the number of points
|
||||
*/
|
||||
m_t0_int.resize(nPoints);
|
||||
m_h0_R_int.resize(nPoints);
|
||||
m_s0_R_int.resize(nPoints);
|
||||
m_cp0_R_int.resize(nPoints);
|
||||
m_mu0_R_int.resize(nPoints);
|
||||
/*
|
||||
* Calculate the T298 interval and make sure that
|
||||
* the temperatures are strictly monotonic.
|
||||
* Also distribute the data into the internal arrays.
|
||||
*/
|
||||
bool ifound = false;
|
||||
for (i = 0, iindex = 2; i < nPoints; i++) {
|
||||
T1 = coeffs[iindex];
|
||||
m_t0_int[i] = T1;
|
||||
m_mu0_R_int[i] = coeffs[iindex+1] / GasConstant;
|
||||
if (T1 == 298.15) {
|
||||
iT298 = i;
|
||||
ifound = true;
|
||||
}
|
||||
if (i < nPoints - 1) {
|
||||
T2 = coeffs[iindex+2];
|
||||
if (T2 <= T1) {
|
||||
throw CanteraError("Mu0Poly",
|
||||
"Temperatures are not monotonic increasing");
|
||||
}
|
||||
}
|
||||
iindex += 2;
|
||||
}
|
||||
if (!ifound) {
|
||||
throw CanteraError("Mu0Poly",
|
||||
"One temperature has to be 298.15");
|
||||
}
|
||||
|
||||
/*
|
||||
* Starting from the interval with T298, we go up
|
||||
*/
|
||||
doublereal mu2, s1, s2, h1, h2, cpi, deltaMu, deltaT;
|
||||
T1 = m_t0_int[iT298];
|
||||
doublereal mu1 = m_mu0_R_int[iT298];
|
||||
m_h0_R_int[iT298] = m_H298;
|
||||
m_s0_R_int[iT298] = - (mu1 - m_h0_R_int[iT298]) / T1;
|
||||
for (i = iT298; i < m_numIntervals; i++) {
|
||||
T1 = m_t0_int[i];
|
||||
s1 = m_s0_R_int[i];
|
||||
h1 = m_h0_R_int[i];
|
||||
mu1 = m_mu0_R_int[i];
|
||||
T2 = m_t0_int[i+1];
|
||||
mu2 = m_mu0_R_int[i+1];
|
||||
deltaMu = mu2 - mu1;
|
||||
deltaT = T2 - T1;
|
||||
cpi = (deltaMu - T1 * s1 + T2 * s1) / (deltaT - T2 * log(T2/T1));
|
||||
h2 = h1 + cpi * deltaT;
|
||||
s2 = s1 + cpi * log(T2/T1);
|
||||
m_cp0_R_int[i] = cpi;
|
||||
m_h0_R_int[i+1] = h2;
|
||||
m_s0_R_int[i+1] = s2;
|
||||
m_cp0_R_int[i+1] = cpi;
|
||||
}
|
||||
|
||||
/*
|
||||
* Starting from the interval with T298, we go down
|
||||
*/
|
||||
if (iT298 > 0) {
|
||||
T2 = m_t0_int[iT298];
|
||||
mu2 = m_mu0_R_int[iT298];
|
||||
m_h0_R_int[iT298] = m_H298;
|
||||
m_s0_R_int[iT298] = - (mu2 - m_h0_R_int[iT298]) / T2;
|
||||
for (i = iT298 - 1; i >= 0; i--) {
|
||||
T1 = m_t0_int[i];
|
||||
mu1 = m_mu0_R_int[i];
|
||||
T2 = m_t0_int[i+1];
|
||||
mu2 = m_mu0_R_int[i+1];
|
||||
s2 = m_s0_R_int[i+1];
|
||||
h2 = m_h0_R_int[i+1];
|
||||
deltaMu = mu2 - mu1;
|
||||
deltaT = T2 - T1;
|
||||
cpi = (deltaMu - T1 * s2 + T2 * s2) / (deltaT - T1 * log(T2/T1));
|
||||
h1 = h2 - cpi * deltaT;
|
||||
s1 = s2 - cpi * log(T2/T1);
|
||||
m_cp0_R_int[i] = cpi;
|
||||
m_h0_R_int[i] = h1;
|
||||
m_s0_R_int[i] = s1;
|
||||
if (i == (m_numIntervals-1)) {
|
||||
m_cp0_R_int[i+1] = cpi;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_HKM_NOT
|
||||
printf(" Temp mu0(J/kmol) cp0(J/kmol/K) "
|
||||
" h0(J/kmol) s0(J/kmol/K) \n");
|
||||
for (i = 0; i < nPoints; i++) {
|
||||
printf("%12.3g %12.5g %12.5g %12.5g %12.5g\n",
|
||||
m_t0_int[i], m_mu0_R_int[i] * GasConstant,
|
||||
m_cp0_R_int[i]* GasConstant,
|
||||
m_h0_R_int[i]* GasConstant,
|
||||
m_s0_R_int[i]* GasConstant);
|
||||
fflush(stdout);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
307
Cantera/src/thermo/Mu0Poly.h
Normal file
307
Cantera/src/thermo/Mu0Poly.h
Normal file
|
|
@ -0,0 +1,307 @@
|
|||
/**
|
||||
* @file Mu0Poly.h
|
||||
* Header for a single-species standard state object derived
|
||||
* from \link Cantera::SpeciesThermoInterpType SpeciesThermoInterpType\endlink based
|
||||
* on a piecewise constant mu0 interpolation
|
||||
* (see \ref spthermo and class \link Cantera::Mu0Poly Mu0Poly\endlink).
|
||||
*/
|
||||
|
||||
/* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef CT_MU0POLY_H
|
||||
#define CT_MU0POLY_H
|
||||
|
||||
#include "SpeciesThermoInterpType.h"
|
||||
|
||||
namespace Cantera {
|
||||
class SpeciesThermo;
|
||||
class XML_Node;
|
||||
|
||||
//! The %Mu0Poly class implements an interpolation of the Gibbs free energy based on a
|
||||
//! piecewise constant heat capacity approximation.
|
||||
/*!
|
||||
* The %Mu0Poly class implements a piecewise constant heat capacity approximation.
|
||||
* of the standard state chemical potential of one
|
||||
* species at a single reference pressure.
|
||||
* The chemical potential is input as a series of (\f$T\f$, \f$ \mu^o(T)\f$)
|
||||
* values. The first temperature is assumed to be equal
|
||||
* to 298.15 K; however, this may be relaxed in the future.
|
||||
* This information, and an assumption of a constant
|
||||
* heat capacity within each interval is enough to
|
||||
* calculate all thermodynamic functions.
|
||||
*
|
||||
* The piece-wise constant heat capacity is calculated from the change in the chemical potential over each interval.
|
||||
* Once the heat capacity is known, the other thermodynamic functions may be determined.
|
||||
* The basic equation for going from temperature point 1 to temperature point 2
|
||||
* are as follows for \f$ T \f$, \f$ T_1 <= T <= T_2 \f$
|
||||
*
|
||||
* \f[
|
||||
* \mu^o(T_1) = h^o(T_1) - T_1 * s^o(T_1)
|
||||
* \f]
|
||||
* \f[
|
||||
* \mu^o(T_2) - \mu^o(T_1) = Cp^o(T_1)(T_2 - T_1) - Cp^o(T_1)(T_2)ln(\frac{T_2}{T_1}) - s^o(T_1)(T_2 - T_1)
|
||||
* \f]
|
||||
* \f[
|
||||
* s^o(T_2) = s^o(T_1) + Cp^o(T_1)ln(\frac{T_2}{T_1})
|
||||
* \f]
|
||||
* \f[
|
||||
* h^o(T_2) = h^o(T_1) + Cp^o(T_1)(T_2 - T_1)
|
||||
* \f]
|
||||
*
|
||||
* Within each interval the following relations are used. For \f$ T \f$, \f$ T_1 <= T <= T_2 \f$
|
||||
*
|
||||
* \f[
|
||||
* \mu^o(T) = \mu^o(T_1) + Cp^o(T_1)(T - T_1) - Cp^o(T_1)(T_2)ln(\frac{T}{T_1}) - s^o(T_1)(T - T_1)
|
||||
* \f]
|
||||
* \f[
|
||||
* s^o(T) = s^o(T_1) + Cp^o(T_1)ln(\frac{T}{T_1})
|
||||
* \f]
|
||||
* \f[
|
||||
* h^o(T) = h^o(T_1) + Cp^o(T_1)(T - T_1)
|
||||
* \f]
|
||||
*
|
||||
* Notes about temperature interpolation for \f$ T < T_1 \f$ and \f$ T > T_{npoints} \f$.
|
||||
* These are achieved by assuming a constant heat capacity
|
||||
* equal to the value in the closest temperature interval.
|
||||
* No error is thrown.
|
||||
*
|
||||
* @note In the future, a better assumption about the heat
|
||||
* capacity may be employed, so that it can be continuous.
|
||||
*
|
||||
* @ingroup spthermo
|
||||
*/
|
||||
class Mu0Poly: public SpeciesThermoInterpType {
|
||||
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
Mu0Poly();
|
||||
|
||||
//! Constructor used in templated instantiations
|
||||
/*!
|
||||
*
|
||||
* In the constructor, we calculate and store the
|
||||
* piecewise linear approximation to the thermodynamic
|
||||
* functions.
|
||||
*
|
||||
* @param n Species index
|
||||
* @param tlow Minimum temperature
|
||||
* @param thigh Maximum temperature
|
||||
* @param pref reference pressure (Pa).
|
||||
* @param coeffs Vector of coefficients used to set the
|
||||
* parameters for the standard state for species n.
|
||||
* There are \f$ 2+npoints*2 \f$ coefficients, where
|
||||
* \f$ npoints \f$ are the number of temperature points.
|
||||
* Their identity is further broken down:
|
||||
* - coeffs[0] = number of points (integer)
|
||||
* - coeffs[1] = \f$ h^o(298.15 K) \f$ (J/kmol)
|
||||
* - coeffs[2] = \f$ T_1 \f$ (Kelvin)
|
||||
* - coeffs[3] = \f$ \mu^o(T_1) \f$ (J/kmol)
|
||||
* - coeffs[4] = \f$ T_2 \f$ (Kelvin)
|
||||
* - coeffs[5] = \f$ \mu^o(T_2) \f$ (J/kmol)
|
||||
* - coeffs[6] = \f$ T_3 \f$ (Kelvin)
|
||||
* - coeffs[7] = \f$ \mu^o(T_3) \f$ (J/kmol)
|
||||
* - ........
|
||||
* .
|
||||
*/
|
||||
Mu0Poly(int n, doublereal tlow, doublereal thigh,
|
||||
doublereal pref, const doublereal* coeffs);
|
||||
|
||||
//! Copy constructor
|
||||
Mu0Poly(const Mu0Poly &);
|
||||
|
||||
//! Assignment operator
|
||||
Mu0Poly& operator=(const Mu0Poly&);
|
||||
|
||||
//! Destructor
|
||||
virtual ~Mu0Poly();
|
||||
|
||||
//! Duplicator
|
||||
virtual SpeciesThermoInterpType *
|
||||
duplMyselfAsSpeciesThermoInterpType() const;
|
||||
|
||||
//! Returns the minimum temperature that the thermo
|
||||
//! parameterization is valid
|
||||
virtual doublereal minTemp() const;
|
||||
|
||||
//! Returns the maximum temperature that the thermo
|
||||
//! parameterization is valid
|
||||
virtual doublereal maxTemp() const;
|
||||
|
||||
//! Returns the reference pressure (Pa)
|
||||
virtual doublereal refPressure() const;
|
||||
|
||||
//! Returns an integer representing the type of parameterization
|
||||
virtual int reportType() const { return MU0_INTERP; }
|
||||
|
||||
|
||||
//! Update the properties for this species, given a temperature polynomial
|
||||
/*!
|
||||
* This method is called with a pointer to an array containing the functions of
|
||||
* temperature needed by this parameterization, and three pointers to arrays where the
|
||||
* computed property values should be written. This method updates only one value in
|
||||
* each array.
|
||||
*
|
||||
* Temperature Polynomial:
|
||||
*
|
||||
* tPoly[0] = temp (Kelvin)
|
||||
*
|
||||
* @param tPoly vector of temperature polynomials. Length = 1
|
||||
* @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).
|
||||
*/
|
||||
virtual void updateProperties(const doublereal* tPoly,
|
||||
doublereal* cp_R, doublereal* h_RT,
|
||||
doublereal* s_R) const ;
|
||||
|
||||
//! Compute the reference-state property of one species
|
||||
/*!
|
||||
* Given temperature T in K, this method updates the values of
|
||||
* the non-dimensional heat capacity at constant pressure,
|
||||
* enthalpy, and entropy, at the reference pressure, Pref
|
||||
* of one of the species. The species index is used
|
||||
* to reference into the cp_R, h_RT, and s_R arrays.
|
||||
*
|
||||
* @param temp 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).
|
||||
*/
|
||||
virtual void updatePropertiesTemp(const doublereal temp,
|
||||
doublereal* cp_R,
|
||||
doublereal* h_RT,
|
||||
doublereal* s_R) const ;
|
||||
|
||||
//!This utility function reports back the type of
|
||||
//! parameterization and all of the parameters for the
|
||||
//! species, index.
|
||||
/*!
|
||||
* All parameters are output variables
|
||||
*
|
||||
* @param n Species index
|
||||
* @param type Integer type of the standard type
|
||||
* @param tlow output - Minimum temperature
|
||||
* @param thigh output - Maximum temperature
|
||||
* @param pref output - reference pressure (Pa).
|
||||
* @param coeffs Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
*/
|
||||
virtual void reportParameters(int &n, int &type,
|
||||
doublereal &tlow, doublereal &thigh,
|
||||
doublereal &pref,
|
||||
doublereal* const coeffs) const;
|
||||
|
||||
//! Modify parameters for the standard state
|
||||
/*!
|
||||
* @param coeffs Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
*/
|
||||
virtual void modifyParameters(doublereal* coeffs);
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Number of intervals in the interpolating linear
|
||||
* approximation. Number of points is one more than the
|
||||
* number of intervals.
|
||||
*/
|
||||
int m_numIntervals;
|
||||
|
||||
/**
|
||||
* Value of the enthalpy at T = 298.15.
|
||||
* This value is tied to the Heat of formation of
|
||||
* the species at 298.15.
|
||||
*/
|
||||
doublereal m_H298;
|
||||
|
||||
/**
|
||||
* Points at which the standard state chemical potential
|
||||
* are given.
|
||||
*/
|
||||
vector_fp m_t0_int;
|
||||
|
||||
/**
|
||||
* Mu0's are primary input data. They aren't strictly
|
||||
* needed, but are kept here for convenience.
|
||||
*/
|
||||
vector_fp m_mu0_R_int;
|
||||
|
||||
//! Dimensionless Enthalpies at the temperature points
|
||||
vector_fp m_h0_R_int;
|
||||
|
||||
//! Entropy at the points
|
||||
vector_fp m_s0_R_int;
|
||||
|
||||
//! Heat capacity at the points
|
||||
vector_fp m_cp0_R_int;
|
||||
//! Limiting low temperature
|
||||
doublereal m_lowT;
|
||||
//! Limiting high temperature
|
||||
doublereal m_highT;
|
||||
|
||||
//! Reference pressure
|
||||
doublereal m_Pref;
|
||||
|
||||
//! Species index
|
||||
int m_index;
|
||||
|
||||
private:
|
||||
|
||||
//! process the coefficients
|
||||
/*!
|
||||
* Mu0Poly():
|
||||
*
|
||||
* In the constructor, we calculate and store the
|
||||
* piecewise linear approximation to the thermodynamic
|
||||
* functions.
|
||||
*
|
||||
* @param coeffs coefficients. These are defined as follows:
|
||||
*
|
||||
* coeffs[0] = number of points (integer)
|
||||
* 1 = H298(J/kmol)
|
||||
* 2 = T1 (Kelvin)
|
||||
* 3 = mu1 (J/kmol)
|
||||
* 4 = T2 (Kelvin)
|
||||
* 5 = mu2 (J/kmol)
|
||||
* 6 = T3 (Kelvin)
|
||||
* 7 = mu3 (J/kmol)
|
||||
* ........
|
||||
*/
|
||||
void processCoeffs(const doublereal * coeffs);
|
||||
|
||||
};
|
||||
|
||||
//! Install a Mu0 polynomial thermodynamic reference state
|
||||
/*!
|
||||
* Install a Mu0 polynomial thermodynamic reference state property
|
||||
* parameterization for species k into a SpeciesThermo instance,
|
||||
* getting the information from an XML database.
|
||||
*
|
||||
* @param speciesName Name of the species
|
||||
* @param sp Owning SpeciesThermo object
|
||||
* @param k Species index
|
||||
* @param Mu0Node_ptr Pointer to the XML element containing the
|
||||
* Mu0 information.
|
||||
*
|
||||
* @ingroup spthermo
|
||||
*/
|
||||
void installMu0ThermoFromXML(std::string speciesName,
|
||||
SpeciesThermo& sp, int k,
|
||||
const XML_Node* Mu0Node_ptr);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
286
Cantera/src/thermo/NasaPoly1.h
Executable file
286
Cantera/src/thermo/NasaPoly1.h
Executable file
|
|
@ -0,0 +1,286 @@
|
|||
|
||||
/**
|
||||
* @file NasaPoly1.h
|
||||
* Header for a single-species standard state object derived
|
||||
* from \link Cantera::SpeciesThermoInterpType SpeciesThermoInterpType\endlink based
|
||||
* on the NASA temperature polynomial form applied to one temperature region
|
||||
* (see \ref spthermo and class \link Cantera::NasaPoly1 NasaPoly1\endlink).
|
||||
*
|
||||
* This parameterization has one NASA temperature region.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CT_NASAPOLY1_H
|
||||
#define CT_NASAPOLY1_H
|
||||
|
||||
|
||||
/* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
// Copyright 2001 California Institute of Technology
|
||||
|
||||
|
||||
#include "global.h"
|
||||
#include "SpeciesThermoInterpType.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
/**
|
||||
* The NASA polynomial parameterization for one temperature range.
|
||||
* This parameterization expresses the heat capacity as a
|
||||
* fourth-order polynomial. Note that this is the form used in the
|
||||
* 1971 NASA equilibrium program and by the Chemkin software
|
||||
* package, but differs from the form used in the more recent NASA
|
||||
* equilibrium program.
|
||||
*
|
||||
* Seven coefficients \f$(a_0,\dots,a_6)\f$ are used to represent
|
||||
* \f$ c_p^0(T)\f$, \f$ h^0(T)\f$, and \f$ s^0(T) \f$ as
|
||||
* polynomials in \f$ T \f$ :
|
||||
* \f[
|
||||
* \frac{c_p(T)}{R} = a_0 + a_1 T + a_2 T^2 + a_3 T^3 + a_4 T^4
|
||||
* \f]
|
||||
* \f[
|
||||
* \frac{h^0(T)}{RT} = a_0 + \frac{a_1}{2} T + \frac{a_2}{3} T^2
|
||||
* + \frac{a_3}{4} T^3 + \frac{a_4}{5} T^4 + \frac{a_5}{T}.
|
||||
* \f]
|
||||
* \f[
|
||||
* \frac{s^0(T)}{R} = a_0\ln T + a_1 T + \frac{a_2}{2} T^2
|
||||
+ \frac{a_3}{3} T^3 + \frac{a_4}{4} T^4 + a_6.
|
||||
* \f]
|
||||
*
|
||||
* This class is designed specifically for use by class NasaThermo.
|
||||
* @ingroup spthermo
|
||||
*/
|
||||
class NasaPoly1 : public SpeciesThermoInterpType {
|
||||
|
||||
public:
|
||||
|
||||
//! Empty constructor
|
||||
NasaPoly1()
|
||||
: m_lowT(0.0), m_highT (0.0),
|
||||
m_Pref(0.0), m_index (0), m_coeff(array_fp(7)) {}
|
||||
|
||||
|
||||
//! constructor used in templated instantiations
|
||||
/*!
|
||||
* @param n Species index
|
||||
* @param tlow Minimum temperature
|
||||
* @param thigh Maximum temperature
|
||||
* @param pref reference pressure (Pa).
|
||||
* @param coeffs Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
*/
|
||||
NasaPoly1(int n, doublereal tlow, doublereal thigh, doublereal pref,
|
||||
const doublereal* coeffs) :
|
||||
m_lowT (tlow),
|
||||
m_highT (thigh),
|
||||
m_Pref (pref),
|
||||
m_index (n),
|
||||
m_coeff (array_fp(7)) {
|
||||
std::copy(coeffs, coeffs + 7, m_coeff.begin());
|
||||
}
|
||||
|
||||
//! copy constructor
|
||||
/*!
|
||||
* @param b object to be copied
|
||||
*/
|
||||
NasaPoly1(const NasaPoly1& b) :
|
||||
m_lowT (b.m_lowT),
|
||||
m_highT (b.m_highT),
|
||||
m_Pref (b.m_Pref),
|
||||
m_index (b.m_index),
|
||||
m_coeff (array_fp(7)) {
|
||||
std::copy(b.m_coeff.begin(),
|
||||
b.m_coeff.begin() + 7,
|
||||
m_coeff.begin());
|
||||
}
|
||||
|
||||
//! assignment operator
|
||||
/*!
|
||||
* @param b object to be copied
|
||||
*/
|
||||
NasaPoly1& operator=(const NasaPoly1& b) {
|
||||
if (&b != this) {
|
||||
m_lowT = b.m_lowT;
|
||||
m_highT = b.m_highT;
|
||||
m_Pref = b.m_Pref;
|
||||
m_index = b.m_index;
|
||||
std::copy(b.m_coeff.begin(),
|
||||
b.m_coeff.begin() + 7,
|
||||
m_coeff.begin());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
virtual ~NasaPoly1(){}
|
||||
|
||||
//! duplicator
|
||||
virtual SpeciesThermoInterpType *
|
||||
duplMyselfAsSpeciesThermoInterpType() const {
|
||||
NasaPoly1* np = new NasaPoly1(*this);
|
||||
return (SpeciesThermoInterpType *) np;
|
||||
}
|
||||
|
||||
//! Returns the minimum temperature that the thermo
|
||||
//! parameterization is valid
|
||||
virtual doublereal minTemp() const { return m_lowT;}
|
||||
|
||||
//! Returns the maximum temperature that the thermo
|
||||
//! parameterization is valid
|
||||
virtual doublereal maxTemp() const { return m_highT;}
|
||||
|
||||
//! Returns the reference pressure (Pa)
|
||||
virtual doublereal refPressure() const { return m_Pref; }
|
||||
|
||||
//! Returns an integer representing the type of parameterization
|
||||
virtual int reportType() const { return NASA1; }
|
||||
|
||||
|
||||
//! Update the properties for this species, given a temperature polynomial
|
||||
/*!
|
||||
* This method is called with a pointer to an array containing the functions of
|
||||
* temperature needed by this parameterization, and three pointers to arrays where the
|
||||
* computed property values should be written. This method updates only one value in
|
||||
* each array.
|
||||
*
|
||||
* Temperature Polynomial:
|
||||
* tt[0] = t;
|
||||
* tt[1] = t*t;
|
||||
* tt[2] = m_t[1]*t;
|
||||
* tt[3] = m_t[2]*t;
|
||||
* tt[4] = 1.0/t;
|
||||
* tt[5] = std::log(t);
|
||||
*
|
||||
* @param tt vector of temperature polynomials
|
||||
* @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).
|
||||
*/
|
||||
virtual void updateProperties(const doublereal* tt,
|
||||
doublereal* cp_R, doublereal* h_RT, doublereal* s_R) const {
|
||||
|
||||
doublereal ct0 = m_coeff[2]; // a0
|
||||
doublereal ct1 = m_coeff[3]*tt[0]; // a1 * T
|
||||
doublereal ct2 = m_coeff[4]*tt[1]; // a2 * T^2
|
||||
doublereal ct3 = m_coeff[5]*tt[2]; // a3 * T^3
|
||||
doublereal ct4 = m_coeff[6]*tt[3]; // a4 * T^4
|
||||
|
||||
doublereal cp, h, s;
|
||||
cp = ct0 + ct1 + ct2 + ct3 + ct4;
|
||||
h = ct0 + 0.5*ct1 + OneThird*ct2 + 0.25*ct3 + 0.2*ct4
|
||||
+ m_coeff[0]*tt[4]; // last term is a5/T
|
||||
s = ct0*tt[5] + ct1 + 0.5*ct2 + OneThird*ct3
|
||||
+0.25*ct4 + m_coeff[1]; // last term is a6
|
||||
|
||||
// return the computed properties in the location in the output
|
||||
// arrays for this species
|
||||
cp_R[m_index] = cp;
|
||||
h_RT[m_index] = h;
|
||||
s_R[m_index] = s;
|
||||
//writelog("NASA1: for species "+int2str(m_index)+", h_RT = "+
|
||||
// fp2str(h)+"\n");
|
||||
}
|
||||
|
||||
|
||||
//! Compute the reference-state property of one species
|
||||
/*!
|
||||
* Given temperature T in K, this method updates the values of
|
||||
* the non-dimensional heat capacity at constant pressure,
|
||||
* enthalpy, and entropy, at the reference pressure, Pref
|
||||
* of one of the species. The species index is used
|
||||
* to reference into the cp_R, h_RT, and s_R arrays.
|
||||
*
|
||||
* @param temp 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).
|
||||
*/
|
||||
virtual void updatePropertiesTemp(const doublereal temp,
|
||||
doublereal* cp_R, doublereal* h_RT,
|
||||
doublereal* s_R) const {
|
||||
double tPoly[6];
|
||||
tPoly[0] = temp;
|
||||
tPoly[1] = temp * temp;
|
||||
tPoly[2] = tPoly[1] * temp;
|
||||
tPoly[3] = tPoly[2] * temp;
|
||||
tPoly[4] = 1.0 / temp;
|
||||
tPoly[5] = std::log(temp);
|
||||
updateProperties(tPoly, cp_R, h_RT, s_R);
|
||||
}
|
||||
|
||||
//!This utility function reports back the type of
|
||||
//! parameterization and all of the parameters for the
|
||||
//! species, index.
|
||||
/*!
|
||||
* All parameters are output variables
|
||||
*
|
||||
* @param n Species index
|
||||
* @param type Integer type of the standard type
|
||||
* @param tlow output - Minimum temperature
|
||||
* @param thigh output - Maximum temperature
|
||||
* @param pref output - reference pressure (Pa).
|
||||
* @param coeffs Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
*/
|
||||
virtual void reportParameters(int &n, int &type,
|
||||
doublereal &tlow, doublereal &thigh,
|
||||
doublereal &pref,
|
||||
doublereal* const coeffs) const {
|
||||
n = m_index;
|
||||
type = NASA1;
|
||||
tlow = m_lowT;
|
||||
thigh = m_highT;
|
||||
pref = m_Pref;
|
||||
coeffs[5] = m_coeff[0];
|
||||
coeffs[6] = m_coeff[1];
|
||||
for (int i = 2; i < 7; i++) {
|
||||
coeffs[i-2] = m_coeff[i];
|
||||
}
|
||||
#ifdef WARN_ABOUT_CHANGES_FROM_VERSION_1_6
|
||||
cout << "************************************************\n"
|
||||
cout << "Warning: NasaPoly1::reportParameters now returns \n"
|
||||
<< "the coefficient array in the same order as in\n"
|
||||
<< "the input file. See file NasaPoly1.h" << endl;
|
||||
cout << "************************************************\n"
|
||||
#endif
|
||||
}
|
||||
|
||||
//! Modify parameters for the standard state
|
||||
/*!
|
||||
* @param coeffs Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
*/
|
||||
virtual void modifyParameters(doublereal* coeffs) {
|
||||
m_coeff[0] = coeffs[5];
|
||||
m_coeff[1] = coeffs[6];
|
||||
for (int i = 0; i < 5; i++) {
|
||||
m_coeff[i+2] = coeffs[i];
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
//! lowest valid temperature
|
||||
doublereal m_lowT;
|
||||
//! highest valid temperature
|
||||
doublereal m_highT;
|
||||
//! standard-state pressure
|
||||
doublereal m_Pref;
|
||||
//! species index
|
||||
int m_index;
|
||||
//! array of polynomial coefficients
|
||||
array_fp m_coeff;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
288
Cantera/src/thermo/NasaPoly2.h
Normal file
288
Cantera/src/thermo/NasaPoly2.h
Normal file
|
|
@ -0,0 +1,288 @@
|
|||
/**
|
||||
* @file NasaPoly2.h
|
||||
* Header for a single-species standard state object derived
|
||||
* from \link Cantera::SpeciesThermoInterpType SpeciesThermoInterpType\endlink based
|
||||
* on the NASA temperature polynomial form applied to two temperature regions
|
||||
* (see \ref spthermo and class \link Cantera::NasaPoly2 NasaPoly2\endlink).
|
||||
*
|
||||
* Two zoned Nasa polynomial parameterization
|
||||
*/
|
||||
|
||||
/* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
// Copyright 2001 California Institute of Technology
|
||||
|
||||
|
||||
#ifndef CT_NASAPOLY2_H
|
||||
#define CT_NASAPOLY2_H
|
||||
|
||||
#include "SpeciesThermoInterpType.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* The NASA polynomial parameterization for two temperature ranges.
|
||||
* This parameterization expresses the heat capacity as a
|
||||
* fourth-order polynomial. Note that this is the form used in the
|
||||
* 1971 NASA equilibrium program and by the Chemkin software
|
||||
* package, but differs from the form used in the more recent NASA
|
||||
* equilibrium program.
|
||||
*
|
||||
* Seven coefficients \f$(a_0,\dots,a_6)\f$ are used to represent
|
||||
* \f$ c_p^0(T)\f$, \f$ h^0(T)\f$, and \f$ s^0(T) \f$ as
|
||||
* polynomials in \f$ T \f$ :
|
||||
* \f[
|
||||
* \frac{c_p(T)}{R} = a_0 + a_1 T + a_2 T^2 + a_3 T^3 + a_4 T^4
|
||||
* \f]
|
||||
* \f[
|
||||
* \frac{h^0(T)}{RT} = a_0 + \frac{a_1}{2} T + \frac{a_2}{3} T^2
|
||||
* + \frac{a_3}{4} T^3 + \frac{a_4}{5} T^4 + \frac{a_5}{T}.
|
||||
* \f]
|
||||
* \f[
|
||||
* \frac{s^0(T)}{R} = a_0\ln T + a_1 T + \frac{a_2}{2} T^2
|
||||
+ \frac{a_3}{3} T^3 + \frac{a_4}{4} T^4 + a_6.
|
||||
* \f]
|
||||
*
|
||||
* This class is designed specifically for use by the class
|
||||
* GeneralSpeciesThermo.
|
||||
*
|
||||
* @ingroup spthermo
|
||||
*/
|
||||
class NasaPoly2 : public SpeciesThermoInterpType {
|
||||
|
||||
public:
|
||||
|
||||
//! Empty constructor
|
||||
NasaPoly2()
|
||||
: m_lowT(0.0),
|
||||
m_midT(0.0),
|
||||
m_highT (0.0),
|
||||
m_Pref(0.0),
|
||||
mnp_low(0),
|
||||
mnp_high(0),
|
||||
m_index(0),
|
||||
m_coeff(array_fp(15)) {
|
||||
}
|
||||
|
||||
//! Full Constructor
|
||||
/*!
|
||||
* @param n Species index
|
||||
* @param tlow output - Minimum temperature
|
||||
* @param thigh output - Maximum temperature
|
||||
* @param pref output - reference pressure (Pa).
|
||||
* @param coeffs Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
*/
|
||||
NasaPoly2(int n, doublereal tlow, doublereal thigh, doublereal pref,
|
||||
const doublereal* coeffs) :
|
||||
m_lowT(tlow),
|
||||
m_highT(thigh),
|
||||
m_Pref(pref),
|
||||
mnp_low(0),
|
||||
mnp_high(0),
|
||||
m_index(n),
|
||||
m_coeff(array_fp(15)) {
|
||||
|
||||
std::copy(coeffs, coeffs + 15, m_coeff.begin());
|
||||
m_midT = coeffs[0];
|
||||
mnp_low = new NasaPoly1(m_index, m_lowT, m_midT,
|
||||
m_Pref, &m_coeff[1]);
|
||||
mnp_high = new NasaPoly1(m_index, m_midT, m_highT,
|
||||
m_Pref, &m_coeff[8]);
|
||||
}
|
||||
|
||||
//! Copy Constructor
|
||||
/*!
|
||||
* @param b objecto to be copied.
|
||||
*/
|
||||
NasaPoly2(const NasaPoly2& b) :
|
||||
m_lowT(b.m_lowT),
|
||||
m_midT(b.m_midT),
|
||||
m_highT(b.m_highT),
|
||||
m_Pref(b.m_Pref),
|
||||
mnp_low(0),
|
||||
mnp_high(0),
|
||||
m_index(b.m_index),
|
||||
m_coeff(array_fp(15)) {
|
||||
|
||||
std::copy(b.m_coeff.begin(),
|
||||
b.m_coeff.begin() + 15,
|
||||
m_coeff.begin());
|
||||
mnp_low = new NasaPoly1(m_index, m_lowT, m_midT,
|
||||
m_Pref, &m_coeff[1]);
|
||||
mnp_high = new NasaPoly1(m_index, m_midT, m_highT,
|
||||
m_Pref, &m_coeff[8]);
|
||||
}
|
||||
|
||||
//! Assignment operator
|
||||
/*!
|
||||
* @param b objecto to be copied.
|
||||
*/
|
||||
NasaPoly2& operator=(const NasaPoly2& b) {
|
||||
if (&b != this) {
|
||||
m_lowT = b.m_lowT;
|
||||
m_midT = b.m_midT;
|
||||
m_highT = b.m_highT;
|
||||
m_Pref = b.m_Pref;
|
||||
m_index = b.m_index;
|
||||
std::copy(b.m_coeff.begin(),
|
||||
b.m_coeff.begin() + 15,
|
||||
m_coeff.begin());
|
||||
if (mnp_low) delete mnp_low;
|
||||
if (mnp_high) delete mnp_high;
|
||||
mnp_low = new NasaPoly1(m_index, m_lowT, m_midT,
|
||||
m_Pref, &m_coeff[1]);
|
||||
mnp_high = new NasaPoly1(m_index, m_midT, m_highT,
|
||||
m_Pref, &m_coeff[8]);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! destructor
|
||||
virtual ~NasaPoly2(){
|
||||
delete mnp_low;
|
||||
delete mnp_high;
|
||||
}
|
||||
|
||||
//! duplicator
|
||||
virtual SpeciesThermoInterpType *
|
||||
duplMyselfAsSpeciesThermoInterpType() const {
|
||||
NasaPoly2* np = new NasaPoly2(*this);
|
||||
return (SpeciesThermoInterpType *) np;
|
||||
}
|
||||
|
||||
//! Returns the minimum temperature that the thermo
|
||||
//! parameterization is valid
|
||||
doublereal minTemp() const { return m_lowT;}
|
||||
|
||||
//! Returns the maximum temperature that the thermo
|
||||
//! parameterization is valid
|
||||
doublereal maxTemp() const { return m_highT;}
|
||||
|
||||
//! Returns the reference pressure (Pa)
|
||||
doublereal refPressure() const { return m_Pref; }
|
||||
|
||||
//! Returns an integer representing the type of parameterization
|
||||
virtual int reportType() const { return NASA2; }
|
||||
|
||||
|
||||
//! Update the properties for this species, given a temperature polynomial
|
||||
/*!
|
||||
* This method is called with a pointer to an array containing the functions of
|
||||
* temperature needed by this parameterization, and three pointers to arrays where the
|
||||
* computed property values should be written. This method updates only one value in
|
||||
* each array.
|
||||
*
|
||||
* Temperature Polynomial:
|
||||
* tt[0] = t;
|
||||
* tt[1] = t*t;
|
||||
* tt[2] = m_t[1]*t;
|
||||
* tt[3] = m_t[2]*t;
|
||||
* tt[4] = 1.0/t;
|
||||
* tt[5] = std::log(t);
|
||||
*
|
||||
* @param tt vector of temperature polynomials
|
||||
* @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).
|
||||
*/
|
||||
void updateProperties(const doublereal* tt,
|
||||
doublereal* cp_R, doublereal* h_RT, doublereal* s_R) const {
|
||||
|
||||
double T = tt[0];
|
||||
if (T <= m_midT) {
|
||||
mnp_low->updateProperties(tt, cp_R, h_RT, s_R);
|
||||
} else {
|
||||
mnp_high->updateProperties(tt, cp_R, h_RT, s_R);
|
||||
}
|
||||
}
|
||||
|
||||
//! Compute the reference-state property of one species
|
||||
/*!
|
||||
* Given temperature T in K, this method updates the values of
|
||||
* the non-dimensional heat capacity at constant pressure,
|
||||
* enthalpy, and entropy, at the reference pressure, Pref
|
||||
* of one of the species. The species index is used
|
||||
* to reference into the cp_R, h_RT, and s_R arrays.
|
||||
*
|
||||
* @param temp 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).
|
||||
*/
|
||||
void updatePropertiesTemp(const doublereal temp,
|
||||
doublereal* cp_R,
|
||||
doublereal* h_RT,
|
||||
doublereal* s_R) const {
|
||||
if (temp <= m_midT) {
|
||||
mnp_low->updatePropertiesTemp(temp, cp_R, h_RT, s_R);
|
||||
} else {
|
||||
mnp_high->updatePropertiesTemp(temp, cp_R, h_RT, s_R);
|
||||
}
|
||||
}
|
||||
|
||||
//!This utility function reports back the type of
|
||||
//! parameterization and all of the parameters for the
|
||||
//! species, index.
|
||||
/*!
|
||||
* All parameters are output variables
|
||||
*
|
||||
* @param n Species index
|
||||
* @param type Integer type of the standard type
|
||||
* @param tlow output - Minimum temperature
|
||||
* @param thigh output - Maximum temperature
|
||||
* @param pref output - reference pressure (Pa).
|
||||
* @param coeffs Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
*/
|
||||
void reportParameters(int &n, int &type,
|
||||
doublereal &tlow, doublereal &thigh,
|
||||
doublereal &pref,
|
||||
doublereal* const coeffs) const {
|
||||
n = m_index;
|
||||
type = NASA2;
|
||||
tlow = m_lowT;
|
||||
thigh = m_highT;
|
||||
pref = m_Pref;
|
||||
for (int i = 0; i < 15; i++) {
|
||||
coeffs[i] = m_coeff[i];
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
//! lowest valid temperature
|
||||
doublereal m_lowT;
|
||||
//! Midrange temperature
|
||||
doublereal m_midT;
|
||||
//! Highest valid temperatre
|
||||
doublereal m_highT;
|
||||
//! Reference state pressure
|
||||
doublereal m_Pref;
|
||||
//! pointer to the NasaPoly1 object for the low temperature region.
|
||||
NasaPoly1 *mnp_low;
|
||||
//! pointer to the NasaPoly1 object for the high temperature region.
|
||||
NasaPoly1 *mnp_high;
|
||||
//! species index
|
||||
int m_index;
|
||||
//! array of polynomial coefficients
|
||||
array_fp m_coeff;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
508
Cantera/src/thermo/NasaThermo.h
Executable file
508
Cantera/src/thermo/NasaThermo.h
Executable file
|
|
@ -0,0 +1,508 @@
|
|||
/**
|
||||
* @file NasaThermo.h
|
||||
* Header for the 2 regime 7 coefficient Nasa thermodynamic
|
||||
* polynomials for multiple species in a phase, derived from the
|
||||
* \link Cantera::SpeciesThermo SpeciesThermo\endlink base class (see \ref spthermo and
|
||||
* \link Cantera::NasaThermo NasaThermo\endlink).
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CT_NASATHERMO_H
|
||||
#define CT_NASATHERMO_H
|
||||
#include <string>
|
||||
|
||||
#include "SpeciesThermoMgr.h"
|
||||
#include "NasaPoly1.h"
|
||||
#include "speciesThermoTypes.h"
|
||||
//#include "polyfit.h"
|
||||
#include "global.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
/**
|
||||
* A species thermodynamic property manager for the NASA
|
||||
* polynomial parameterization with two temperature ranges.
|
||||
*
|
||||
* This class is designed to efficiently evaluate the properties
|
||||
* of a large number of species with the NASA parameterization.
|
||||
*
|
||||
* The original NASA polynomial parameterization expressed the
|
||||
* heat capacity as a fourth-order polynomial in temperature, with
|
||||
* separate coefficients for each of two temperature ranges. (The
|
||||
* newer NASA format adds coefficients for 1/T and 1/T^2, and
|
||||
* allows multiple temperature ranges.) This class is designed for
|
||||
* use with the original parameterization, which is used, for
|
||||
* example, by the Chemkin software package.
|
||||
*
|
||||
* In many cases, the midpoint temperature is the same for many
|
||||
* species. To take advantage of this, class NasaThermo groups
|
||||
* species with a common midpoint temperature, so that checking
|
||||
* which range the desired temperature is in need be done only
|
||||
* once for each group.
|
||||
*
|
||||
* @note There is a special CTML element for entering the
|
||||
* coefficients of this parameterization.
|
||||
* @see importCTML
|
||||
*
|
||||
* @ingroup spthermo
|
||||
*/
|
||||
class NasaThermo : public SpeciesThermo {
|
||||
|
||||
public:
|
||||
|
||||
//! Initialized to the type of parameterization
|
||||
/*!
|
||||
* Note, this value is used in some template functions
|
||||
*/
|
||||
const int ID;
|
||||
|
||||
//! constructor
|
||||
NasaThermo() :
|
||||
ID(NASA),
|
||||
m_tlow_max(0.0),
|
||||
m_thigh_min(1.e30),
|
||||
m_p0(-1.0),
|
||||
m_ngroups(0)
|
||||
{
|
||||
m_t.resize(6);
|
||||
}
|
||||
|
||||
//! destructor
|
||||
virtual ~NasaThermo() {}
|
||||
|
||||
//! install a new species thermodynamic property
|
||||
//! parameterization for one species.
|
||||
/*!
|
||||
*
|
||||
* @param name Name of the species
|
||||
* @param index The 'update' method will update the property
|
||||
* values for this species
|
||||
* at position i index in the property arrays.
|
||||
* @param type int flag specifying the type of parameterization to be
|
||||
* installed.
|
||||
* @param c vector of coefficients for the parameterization.
|
||||
* - c[0] midpoint temperature
|
||||
* - c[1] - c[7] coefficients for low T range
|
||||
* - c[8] - c[14] coefficients for high T range
|
||||
* @param minTemp minimum temperature for which this parameterization
|
||||
* is valid.
|
||||
* @param maxTemp maximum temperature for which this parameterization
|
||||
* is valid.
|
||||
* @param refPressure standard-state pressure for this
|
||||
* parameterization.
|
||||
* @see speciesThermoTypes.h
|
||||
*/
|
||||
virtual void install(string name, int index, int type,
|
||||
const doublereal* c,
|
||||
doublereal minTemp, doublereal maxTemp,
|
||||
doublereal refPressure) {
|
||||
|
||||
m_name[index] = name;
|
||||
int imid = int(c[0]); // midpoint temp converted to integer
|
||||
int igrp = m_index[imid]; // has this value been seen before?
|
||||
if (igrp == 0) { // if not, prepare new group
|
||||
vector<NasaPoly1> v;
|
||||
m_high.push_back(v);
|
||||
m_low.push_back(v);
|
||||
m_tmid.push_back(c[0]);
|
||||
m_index[imid] = igrp = static_cast<int>(m_high.size());
|
||||
m_ngroups++;
|
||||
}
|
||||
|
||||
m_group_map[index] = igrp;
|
||||
m_posInGroup_map[index] = (int) m_low[igrp-1].size();
|
||||
|
||||
doublereal tlow = minTemp;
|
||||
doublereal tmid = c[0];
|
||||
doublereal thigh = maxTemp;
|
||||
const doublereal* clow = c + 1;
|
||||
|
||||
vector_fp chigh(7);
|
||||
copy(c + 8, c + 15, chigh.begin());
|
||||
|
||||
m_high[igrp-1].push_back(NasaPoly1(index, tmid, thigh,
|
||||
refPressure, &chigh[0]));
|
||||
m_low[igrp-1].push_back(NasaPoly1(index, tlow, tmid,
|
||||
refPressure, clow));
|
||||
|
||||
vector_fp clu(7), chu(7);
|
||||
clu[5] = clow[0];
|
||||
clu[6] = clow[1];
|
||||
copy(clow+2, clow+7, clu.begin());
|
||||
chu[5] = chigh[0];
|
||||
chu[6] = chigh[1];
|
||||
copy(chigh.begin()+2, chigh.begin()+7, chu.begin());
|
||||
|
||||
checkContinuity(name, tmid, &clu[0], &chu[0]);
|
||||
|
||||
if (tlow > m_tlow_max) m_tlow_max = tlow;
|
||||
if (thigh < m_thigh_min) m_thigh_min = thigh;
|
||||
if ((int) m_tlow.size() < index + 1) {
|
||||
m_tlow.resize(index + 1, tlow);
|
||||
m_thigh.resize(index + 1, thigh);
|
||||
}
|
||||
m_tlow[index] = tlow;
|
||||
m_thigh[index] = thigh;
|
||||
if (m_p0 < 0.0) {
|
||||
m_p0 = refPressure;
|
||||
} else if (fabs(m_p0 - refPressure) > 0.1) {
|
||||
string logmsg = " WARNING NasaThermo: New Species, " + name + ", has a different reference pressure, "
|
||||
+ fp2str(refPressure) + ", than existing reference pressure, " + fp2str(m_p0) + "\n";
|
||||
writelog(logmsg);
|
||||
logmsg = " This may become a fatal error in the future \n";
|
||||
writelog(logmsg);
|
||||
}
|
||||
m_p0 = refPressure;
|
||||
}
|
||||
|
||||
//! 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).
|
||||
*
|
||||
*/
|
||||
virtual void update_one(int k, doublereal t, doublereal* cp_R,
|
||||
doublereal* h_RT, doublereal* s_R) const {
|
||||
|
||||
m_t[0] = t;
|
||||
m_t[1] = t*t;
|
||||
m_t[2] = m_t[1]*t;
|
||||
m_t[3] = m_t[2]*t;
|
||||
m_t[4] = 1.0/t;
|
||||
m_t[5] = log(t);
|
||||
|
||||
int grp = m_group_map[k];
|
||||
int pos = m_posInGroup_map[k];
|
||||
const vector<NasaPoly1> &mlg = m_low[grp-1];
|
||||
const NasaPoly1 *nlow = &(mlg[pos]);
|
||||
|
||||
doublereal tmid = nlow->maxTemp();
|
||||
if (t < tmid) {
|
||||
nlow->updateProperties(&m_t[0], cp_R, h_RT, s_R);
|
||||
} else {
|
||||
const vector<NasaPoly1> &mhg = m_high[grp-1];
|
||||
const NasaPoly1 *nhigh = &(mhg[pos]);
|
||||
nhigh->updateProperties(&m_t[0], cp_R, h_RT, s_R);
|
||||
}
|
||||
}
|
||||
|
||||
//! Compute the reference-state properties for all species.
|
||||
/*!
|
||||
* Given temperature T in K, this method updates the values of
|
||||
* the non-dimensional heat capacity at constant pressure,
|
||||
* enthalpy, and entropy, at the reference pressure, Pref
|
||||
* of each of the standard states.
|
||||
*
|
||||
* @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).
|
||||
*/
|
||||
virtual void update(doublereal t, doublereal* cp_R,
|
||||
doublereal* h_RT, doublereal* s_R) const {
|
||||
int i;
|
||||
|
||||
// load functions of temperature into m_t vector
|
||||
m_t[0] = t;
|
||||
m_t[1] = t*t;
|
||||
m_t[2] = m_t[1]*t;
|
||||
m_t[3] = m_t[2]*t;
|
||||
m_t[4] = 1.0/t;
|
||||
m_t[5] = log(t);
|
||||
|
||||
// iterate over the groups
|
||||
vector<NasaPoly1>::const_iterator _begin, _end;
|
||||
for (i = 0; i != m_ngroups; i++) {
|
||||
if (t > m_tmid[i]) {
|
||||
_begin = m_high[i].begin();
|
||||
_end = m_high[i].end();
|
||||
}
|
||||
else {
|
||||
_begin = m_low[i].begin();
|
||||
_end = m_low[i].end();
|
||||
}
|
||||
for (; _begin != _end; ++_begin)
|
||||
_begin->updateProperties(&m_t[0], cp_R, h_RT, s_R);
|
||||
}
|
||||
}
|
||||
|
||||
//! Minimum temperature.
|
||||
/*!
|
||||
* If no argument is supplied, this
|
||||
* method returns the minimum temperature for which \e all
|
||||
* parameterizations are valid. If an integer index k is
|
||||
* supplied, then the value returned is the minimum
|
||||
* temperature for species k in the phase.
|
||||
*
|
||||
* @param k Species index
|
||||
*/
|
||||
virtual doublereal minTemp(int k=-1) const {
|
||||
if (k < 0)
|
||||
return m_tlow_max;
|
||||
else
|
||||
return m_tlow[k];
|
||||
}
|
||||
|
||||
//! Maximum temperature.
|
||||
/*!
|
||||
* If no argument is supplied, this
|
||||
* method returns the maximum temperature for which \e all
|
||||
* parameterizations are valid. If an integer index k is
|
||||
* supplied, then the value returned is the maximum
|
||||
* temperature for parameterization k.
|
||||
*
|
||||
* @param k Species index
|
||||
*/
|
||||
virtual doublereal maxTemp(int k=-1) const {
|
||||
if (k < 0)
|
||||
return m_thigh_min;
|
||||
else
|
||||
return m_thigh[k];
|
||||
}
|
||||
|
||||
//! The reference-state pressure for species k.
|
||||
/*!
|
||||
*
|
||||
* returns the reference state pressure in Pascals for
|
||||
* species k. If k is left out of the argument list,
|
||||
* it returns the reference state pressure for the first
|
||||
* species.
|
||||
* Note that some SpeciesThermo implementations, such
|
||||
* as those for ideal gases, require that all species
|
||||
* in the same phase have the same reference state pressures.
|
||||
*
|
||||
* @param k Species index
|
||||
*/
|
||||
virtual doublereal refPressure(int k = -1) const {
|
||||
return m_p0;
|
||||
}
|
||||
|
||||
//! This utility function reports the type of parameterization
|
||||
//! used for the species with index number index.
|
||||
/*!
|
||||
*
|
||||
* @param index Species index
|
||||
*/
|
||||
virtual int reportType(int index) const { return NASA; }
|
||||
|
||||
/*!
|
||||
* This utility function reports back the type of
|
||||
* parameterization and all of the parameters for the
|
||||
* species, index.
|
||||
*
|
||||
* @param index Species index
|
||||
* @param type Integer type of the standard type
|
||||
* @param c Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
* For the NASA object, there are 15 coefficients.
|
||||
* @param minTemp output - Minimum temperature
|
||||
* @param maxTemp output - Maximum temperature
|
||||
* @param refPressure output - reference pressure (Pa).
|
||||
*/
|
||||
virtual void reportParams(int index, int &type,
|
||||
doublereal * const c,
|
||||
doublereal &minTemp,
|
||||
doublereal &maxTemp,
|
||||
doublereal &refPressure) const {
|
||||
type = reportType(index);
|
||||
if (type == NASA) {
|
||||
int grp = m_group_map[index];
|
||||
int pos = m_posInGroup_map[index];
|
||||
const vector<NasaPoly1> &mlg = m_low[grp-1];
|
||||
const vector<NasaPoly1> &mhg = m_high[grp-1];
|
||||
const NasaPoly1 *lowPoly = &(mlg[pos]);
|
||||
const NasaPoly1 *highPoly = &(mhg[pos]);
|
||||
int itype = NASA;
|
||||
doublereal tmid = lowPoly->maxTemp();
|
||||
c[0] = tmid;
|
||||
int n;
|
||||
double ttemp;
|
||||
lowPoly->reportParameters(n, itype, minTemp, ttemp, refPressure,
|
||||
c + 1);
|
||||
if (n != index) {
|
||||
throw CanteraError(" ", "confused");
|
||||
}
|
||||
if (itype != NASA1) {
|
||||
throw CanteraError(" ", "confused");
|
||||
}
|
||||
highPoly->reportParameters(n, itype, ttemp, maxTemp, refPressure,
|
||||
c + 8);
|
||||
if (n != index) {
|
||||
throw CanteraError(" ", "confused");
|
||||
}
|
||||
if (itype != NASA1) {
|
||||
throw CanteraError(" ", "confused");
|
||||
}
|
||||
} else {
|
||||
throw CanteraError(" ", "confused");
|
||||
}
|
||||
}
|
||||
|
||||
//! Modify parameters for the standard state
|
||||
/*!
|
||||
* This utility function modifies the array of coefficients.
|
||||
* The array is the same as that returned by reportParams, so
|
||||
* a call can first be made to reportParams to populate the
|
||||
* array, and then modifyParams can be called to alter
|
||||
* selected values. For the NASA object, there are 15
|
||||
* coefficients.
|
||||
|
||||
* @param index Species index
|
||||
* @param c Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
*/
|
||||
virtual void modifyParams(int index, doublereal *c) {
|
||||
int type = reportType(index);
|
||||
if (type == NASA) {
|
||||
int grp = m_group_map[index];
|
||||
int pos = m_posInGroup_map[index];
|
||||
vector<NasaPoly1> &mlg = m_low[grp-1];
|
||||
vector<NasaPoly1> &mhg = m_high[grp-1];
|
||||
NasaPoly1 *lowPoly = &(mlg[pos]);
|
||||
NasaPoly1 *highPoly = &(mhg[pos]);
|
||||
doublereal tmid = lowPoly->maxTemp();
|
||||
if (c[0] != tmid) {
|
||||
throw CanteraError(" ", "Tmid cannot be changed");
|
||||
}
|
||||
lowPoly->modifyParameters(c + 1);
|
||||
highPoly->modifyParameters(c + 8);
|
||||
checkContinuity(m_name[index], c[0], c + 1, c + 8);
|
||||
} else {
|
||||
throw CanteraError(" ", "confused");
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
//! Vector of vector of NasaPoly1's for the high temp region.
|
||||
/*!
|
||||
* This is the high temp region representation.
|
||||
* The first Length is equal to the number of groups.
|
||||
* The second vector is equal to the number of species
|
||||
* in that particular group.
|
||||
*/
|
||||
vector<vector<NasaPoly1> > m_high;
|
||||
|
||||
//! Vector of vector of NasaPoly1's for the low temp region.
|
||||
/*!
|
||||
* This is the low temp region representation.
|
||||
* The first Length is equal to the number of groups.
|
||||
* The second vector is equal to the number of species
|
||||
* in that particular group.
|
||||
*/
|
||||
vector<vector<NasaPoly1> > m_low;
|
||||
|
||||
//! Map between the midpoint temperature, as an int, to the group number
|
||||
/*!
|
||||
* Length is equal to the number of groups. Only used in the setup.
|
||||
*/
|
||||
map<int, int> m_index;
|
||||
|
||||
//! Vector of log temperature limits
|
||||
/*!
|
||||
* Length is equal to the number of groups.
|
||||
*/
|
||||
vector_fp m_tmid;
|
||||
|
||||
//! Maximum value of the low temperature limit
|
||||
doublereal m_tlow_max;
|
||||
|
||||
//! Minimum value of the high temperature limit
|
||||
doublereal m_thigh_min;
|
||||
|
||||
//! Vector of low temperature limits (species index)
|
||||
/*!
|
||||
* Length is equal to number of species
|
||||
*/
|
||||
vector_fp m_tlow;
|
||||
|
||||
//! Vector of low temperature limits (species index)
|
||||
/*!
|
||||
* Length is equal to number of species
|
||||
*/
|
||||
vector_fp m_thigh;
|
||||
|
||||
//! Reference pressure (Pa)
|
||||
/*!
|
||||
* all species must have the same reference pressure.
|
||||
*/
|
||||
doublereal m_p0;
|
||||
|
||||
//! number of groups
|
||||
int m_ngroups;
|
||||
|
||||
//! Vector of temperature polynomials
|
||||
mutable vector_fp m_t;
|
||||
|
||||
/*!
|
||||
* This map takes as its index, the species index in the phase.
|
||||
* It returns the group index, where the temperature polynomials
|
||||
* for that species are stored. group indecises start at 1,
|
||||
* so a decrement is always performed to access vectors.
|
||||
*/
|
||||
mutable map<int, int> m_group_map;
|
||||
|
||||
/*!
|
||||
* This map takes as its index, the species index in the phase.
|
||||
* It returns the position index within the group, where the
|
||||
* temperature polynomials for that species are storred.
|
||||
*/
|
||||
mutable map<int, int> m_posInGroup_map;
|
||||
|
||||
//! Species name as a function of the species index
|
||||
mutable map<int, string> m_name;
|
||||
|
||||
private:
|
||||
|
||||
//! see SpeciesThermoFactory.cpp for the definition
|
||||
/*!
|
||||
* @param name string name of species
|
||||
* @param tmid Mid temperature, between the two temperature regions
|
||||
* @param clow coefficients for lower temperature region
|
||||
* @param chigh coefficients for higher temperature region
|
||||
*/
|
||||
void checkContinuity(std::string name, double tmid, const doublereal* clow,
|
||||
doublereal* chigh);
|
||||
|
||||
//! for internal use by checkContinuity
|
||||
/*!
|
||||
* @param t temperature
|
||||
* @param c coefficient array
|
||||
*/
|
||||
doublereal enthalpy_RT(double t, const doublereal* c) {
|
||||
return c[0] + 0.5*c[1]*t + OneThird*c[2]*t*t
|
||||
+ 0.25*c[3]*t*t*t + 0.2*c[4]*t*t*t*t
|
||||
+ c[5]/t;
|
||||
}
|
||||
|
||||
//! for internal use by checkContinuity
|
||||
/*!
|
||||
* @param t temperature
|
||||
* @param c coefficient array
|
||||
*/
|
||||
doublereal entropy_R(double t, const doublereal* c) {
|
||||
return c[0]*log(t) + c[1]*t + 0.5*c[2]*t*t
|
||||
+ OneThird*c[3]*t*t*t + 0.25*c[4]*t*t*t*t
|
||||
+ c[6];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -17,7 +17,8 @@
|
|||
#include "xml.h"
|
||||
#include "ctml.h"
|
||||
#include "PDSS.h"
|
||||
#include "importCTML.h"
|
||||
//#include "importCTML.h"
|
||||
#include "ThermoFactory.h"
|
||||
#include "SpeciesThermo.h"
|
||||
|
||||
#include "ThermoPhase.h"
|
||||
|
|
|
|||
328
Cantera/src/thermo/Phase.cpp
Executable file
328
Cantera/src/thermo/Phase.cpp
Executable file
|
|
@ -0,0 +1,328 @@
|
|||
/**
|
||||
* @file Phase.cpp
|
||||
* Definition file for class, Phase, which contains functions for setting the
|
||||
* state of a phase, and for referencing species by name
|
||||
* (see \ref phases and class \link Cantera::Phase Phase\endlink).
|
||||
*/
|
||||
|
||||
// Copyright 2001 California Institute of Technology
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma warning(disable:4786)
|
||||
#pragma warning(disable:4503)
|
||||
#endif
|
||||
|
||||
#include "ct_defs.h"
|
||||
#include "Phase.h"
|
||||
#include "vec_functions.h"
|
||||
#include "ctexceptions.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
|
||||
/*
|
||||
* Copy Constructor
|
||||
*
|
||||
* This function just does the default initialization, and
|
||||
* then calls the assignment operator.
|
||||
*/
|
||||
Phase::Phase(const Phase &right) :
|
||||
m_kk(-1),
|
||||
m_ndim(3),
|
||||
m_index(-1),
|
||||
m_xml(new XML_Node("phase")),
|
||||
m_id("<phase>"),
|
||||
m_name("")
|
||||
{
|
||||
/*
|
||||
* Call the assignment operator.
|
||||
*/
|
||||
*this = operator=(right);
|
||||
}
|
||||
|
||||
/*
|
||||
* Assignment operator
|
||||
*
|
||||
* This operation is sort of complicated. We have to
|
||||
* call the assignment operator for the Constituents and
|
||||
* State operators that Phase inherits from. Then,
|
||||
* we have to copy our own data, making sure to do a
|
||||
* deep copy on the XML_Node data owned by this object.
|
||||
*/
|
||||
const Phase &Phase::operator=(const Phase &right) {
|
||||
/*
|
||||
* Check for self assignment.
|
||||
*/
|
||||
if (this == &right) return *this;
|
||||
/*
|
||||
* Now call the inherited-classes assignment operators.
|
||||
*/
|
||||
(void) Constituents::operator=(right);
|
||||
(void) State::operator=(right);
|
||||
/*
|
||||
* Handle its own data
|
||||
*/
|
||||
m_kk = right.m_kk;
|
||||
m_ndim = right.m_ndim;
|
||||
m_index = right.m_index;
|
||||
m_data = right.m_data;
|
||||
/*
|
||||
* This is a little complicated. -> Because we delete m_xml
|
||||
* in the destructor, we own m_xml completely, and we need
|
||||
* to have our own individual copies of the XML data tree
|
||||
* in each object
|
||||
*/
|
||||
m_xml = new XML_Node(*(right.m_xml));
|
||||
m_id = right.m_id;
|
||||
m_name = right.m_name;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void Phase::saveState(vector_fp& state) const {
|
||||
state.resize(nSpecies() + 2);
|
||||
saveState(state.size(),&(state[0]));
|
||||
}
|
||||
void Phase::saveState(int lenstate, doublereal* state) const {
|
||||
state[0] = temperature();
|
||||
state[1] = density();
|
||||
getMassFractions(state + 2);
|
||||
}
|
||||
|
||||
void Phase::restoreState(const vector_fp& state) {
|
||||
restoreState(state.size(),&state[0]);
|
||||
}
|
||||
|
||||
void Phase::restoreState(int lenstate, const doublereal* state) {
|
||||
if (int(lenstate) >= nSpecies() + 2) {
|
||||
setMassFractions_NoNorm(state + 2);
|
||||
setTemperature(state[0]);
|
||||
setDensity(state[1]);
|
||||
}
|
||||
else {
|
||||
throw ArraySizeError("Phase::restoreState",
|
||||
lenstate,nSpecies()+2);
|
||||
}
|
||||
}
|
||||
|
||||
void Phase::setMoleFractionsByName(compositionMap& xMap) {
|
||||
int kk = nSpecies();
|
||||
doublereal x;
|
||||
vector_fp mf(kk, 0.0);
|
||||
for (int k = 0; k < kk; k++) {
|
||||
x = xMap[speciesName(k)];
|
||||
if (x > 0.0) mf[k] = x;
|
||||
}
|
||||
setMoleFractions(&mf[0]);
|
||||
}
|
||||
|
||||
void Phase::setMoleFractionsByName(const std::string& x) {
|
||||
compositionMap xx;
|
||||
int kk = nSpecies();
|
||||
for (int k = 0; k < kk; k++) {
|
||||
xx[speciesName(k)] = -1.0;
|
||||
}
|
||||
parseCompString(x, xx);
|
||||
setMoleFractionsByName(xx);
|
||||
//int kk = nSpecies();
|
||||
//vector_fp mf(kk);
|
||||
//for (int k = 0; k < kk; k++) {
|
||||
// mf[k] = xx[speciesName(k)];
|
||||
//}
|
||||
//setMoleFractions(mf.begin());
|
||||
}
|
||||
|
||||
void Phase::setMassFractionsByName(compositionMap& yMap) {
|
||||
int kk = nSpecies();
|
||||
doublereal y;
|
||||
vector_fp mf(kk, 0.0);
|
||||
for (int k = 0; k < kk; k++) {
|
||||
y = yMap[speciesName(k)];
|
||||
if (y > 0.0) mf[k] = y;
|
||||
}
|
||||
setMassFractions(&mf[0]);
|
||||
}
|
||||
|
||||
void Phase::setMassFractionsByName(const std::string& y) {
|
||||
compositionMap yy;
|
||||
int kk = nSpecies();
|
||||
for (int k = 0; k < kk; k++) {
|
||||
yy[speciesName(k)] = -1.0;
|
||||
}
|
||||
parseCompString(y, yy);
|
||||
setMassFractionsByName(yy);
|
||||
}
|
||||
|
||||
/** Set the temperature (K), density (kg/m^3), and mole fractions. */
|
||||
void Phase::setState_TRX(doublereal t, doublereal dens,
|
||||
const doublereal* x) {
|
||||
setMoleFractions(x); setTemperature(t); setDensity(dens);
|
||||
}
|
||||
|
||||
void Phase::setState_TNX(doublereal t, doublereal n,
|
||||
const doublereal* x) {
|
||||
setMoleFractions(x); setTemperature(t); setMolarDensity(n);
|
||||
}
|
||||
|
||||
/** Set the temperature (K), density (kg/m^3), and mole fractions. */
|
||||
void Phase::setState_TRX(doublereal t, doublereal dens,
|
||||
compositionMap& x) {
|
||||
setMoleFractionsByName(x); setTemperature(t); setDensity(dens);
|
||||
}
|
||||
|
||||
/** Set the temperature (K), density (kg/m^3), and mass fractions. */
|
||||
void Phase::setState_TRY(doublereal t, doublereal dens,
|
||||
const doublereal* y) {
|
||||
setMassFractions(y); setTemperature(t); setDensity(dens);
|
||||
}
|
||||
|
||||
/** Set the temperature (K), density (kg/m^3), and mass fractions. */
|
||||
void Phase::setState_TRY(doublereal t, doublereal dens,
|
||||
compositionMap& y) {
|
||||
setMassFractionsByName(y); setTemperature(t); setDensity(dens);
|
||||
}
|
||||
|
||||
/** Set the temperature (K) and density (kg/m^3) */
|
||||
void Phase::setState_TR(doublereal t, doublereal rho) {
|
||||
setTemperature(t); setDensity(rho);
|
||||
}
|
||||
|
||||
/** Set the temperature (K) and mole fractions. */
|
||||
void Phase::setState_TX(doublereal t, doublereal* x) {
|
||||
setTemperature(t); setMoleFractions(x);
|
||||
}
|
||||
|
||||
/** Set the temperature (K) and mass fractions. */
|
||||
void Phase::setState_TY(doublereal t, doublereal* y) {
|
||||
setTemperature(t); setMassFractions(y);
|
||||
}
|
||||
|
||||
/** Set the density (kg/m^3) and mole fractions. */
|
||||
void Phase::setState_RX(doublereal rho, doublereal* x) {
|
||||
setMoleFractions(x); setDensity(rho);
|
||||
}
|
||||
|
||||
/** Set the density (kg/m^3) and mass fractions. */
|
||||
void Phase::setState_RY(doublereal rho, doublereal* y) {
|
||||
setMassFractions(y); setDensity(rho);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the vector of molecular weights into vector weights.
|
||||
*/
|
||||
void Phase::getMolecularWeights(vector_fp& weights) {
|
||||
const array_fp& mw = Constituents::molecularWeights();
|
||||
if (weights.size() < mw.size()) weights.resize(mw.size());
|
||||
copy(mw.begin(), mw.end(), weights.begin());
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the vector of molecular weights into array weights.
|
||||
* @deprecated
|
||||
*/
|
||||
void Phase::getMolecularWeights(int iwt, doublereal* weights) {
|
||||
const array_fp& mw = Constituents::molecularWeights();
|
||||
copy(mw.begin(), mw.end(), weights);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the vector of molecular weights into array weights.
|
||||
*/
|
||||
void Phase::getMolecularWeights(doublereal* weights) {
|
||||
const array_fp& mw = Constituents::molecularWeights();
|
||||
copy(mw.begin(), mw.end(), weights);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a const reference to the internal vector of
|
||||
* molecular weights.
|
||||
*/
|
||||
const array_fp& Phase::molecularWeights() {
|
||||
return Constituents::molecularWeights();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the mole fractions by name.
|
||||
*/
|
||||
void Phase::getMoleFractionsByName(compositionMap& x) {
|
||||
x.clear();
|
||||
int kk = nSpecies();
|
||||
for (int k = 0; k < kk; k++) {
|
||||
x[speciesName(k)] = State::moleFraction(k);
|
||||
}
|
||||
}
|
||||
|
||||
doublereal Phase::moleFraction(int k) const {
|
||||
return State::moleFraction(k);
|
||||
}
|
||||
|
||||
doublereal Phase::moleFraction(std::string name) const {
|
||||
int iloc = speciesIndex(name);
|
||||
if (iloc >= 0) return State::moleFraction(iloc);
|
||||
else return 0.0;
|
||||
}
|
||||
|
||||
doublereal Phase::massFraction(int k) const {
|
||||
return State::massFraction(k);
|
||||
}
|
||||
|
||||
doublereal Phase::massFraction(std::string name) const {
|
||||
int iloc = speciesIndex(name);
|
||||
if (iloc >= 0) return massFractions()[iloc];
|
||||
else return 0.0;
|
||||
}
|
||||
|
||||
doublereal Phase::chargeDensity() const {
|
||||
int k;
|
||||
int nsp = nSpecies();
|
||||
doublereal cdens = 0.0;
|
||||
for (k = 0; k < nsp; k++)
|
||||
cdens += charge(k)*State::moleFraction(k);
|
||||
cdens *= Faraday;
|
||||
return cdens;
|
||||
}
|
||||
|
||||
|
||||
// void Phase::update_T(int n) const {
|
||||
// m_T_updater.update(n);
|
||||
// }
|
||||
|
||||
// void Phase::update_C(int n) const {
|
||||
// m_C_updater.update(n);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Finished adding species, prepare to use them for calculation
|
||||
* of mixture properties.
|
||||
*/
|
||||
void Phase::freezeSpecies() {
|
||||
Constituents::freezeSpecies();
|
||||
init(Constituents::molecularWeights());
|
||||
int kk = nSpecies();
|
||||
int nv = kk + 2;
|
||||
m_data.resize(nv,0.0);
|
||||
m_data[0] = 300.0;
|
||||
m_data[1] = 0.001;
|
||||
m_data[2] = 1.0;
|
||||
|
||||
//setState_TRY(300.0, density(), &m_data[2]);
|
||||
|
||||
m_kk = nSpecies();
|
||||
}
|
||||
|
||||
bool Phase::ready() const {
|
||||
return (m_kk > 0 && Constituents::ready() && State::ready());
|
||||
}
|
||||
|
||||
// int Phase::installUpdater_T(Updater* u) {
|
||||
// return m_T_updater.install(u);
|
||||
// }
|
||||
|
||||
// int Phase::installUpdater_C(Updater* u) {
|
||||
// return m_C_updater.install(u);
|
||||
// }
|
||||
}
|
||||
512
Cantera/src/thermo/Phase.h
Executable file
512
Cantera/src/thermo/Phase.h
Executable file
|
|
@ -0,0 +1,512 @@
|
|||
/**
|
||||
* @file Phase.h
|
||||
* Header file for class, Phase, which contains functions for setting the
|
||||
* state of a phase, and for referencing species by name, and also contains text for the module phases
|
||||
* (see \ref phases and class \link Cantera::Phase Phase\endlink).
|
||||
*/
|
||||
/*
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
// Copyright 2001 California Institute of Technology
|
||||
|
||||
#ifndef CT_PHASE_H
|
||||
#define CT_PHASE_H
|
||||
|
||||
#include "State.h"
|
||||
#include "Constituents.h"
|
||||
#include "vec_functions.h"
|
||||
|
||||
#include "ctml.h"
|
||||
using namespace ctml;
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup phases Phases of Matter
|
||||
*
|
||||
* These classes are used to represent the composition and state of a
|
||||
* single phase of matter.
|
||||
* Together these classes form the basis for describing the species and
|
||||
* element compositions of a phase as well as the stoichiometry
|
||||
* of each species, and for describing the current state of the
|
||||
* phase. They do not in themselves contain Thermodynamic equation of
|
||||
* state information. However, they do comprise all of the necessary
|
||||
* background functionality to support thermodynamic calculations, and the
|
||||
* class ThermoPhase inherits from the class Phase (see \ref thermoprops).
|
||||
*
|
||||
* Class Elements manages the elements that are part of a
|
||||
* chemistry specification for a phase. This class may support calculations
|
||||
* employing Multiple phases. In this case, a single Elements object may
|
||||
* be shared by more than one Constituents class. Reactions between
|
||||
* the phases may then be described using stoichiometry base on the
|
||||
* same Elements class object.
|
||||
*
|
||||
* The member functions of class %Elements return information about the elements described
|
||||
* in a particular instantiation of the class.
|
||||
*
|
||||
* Class %Constituents is designed to provide information
|
||||
* about the elements and species in a phase - names, index
|
||||
* numbers (location in arrays), atomic or molecular weights,
|
||||
* etc. No computations are performed by the methods of this
|
||||
* class. The set of elements must include all those that compose
|
||||
* the species, but may include additional elements.
|
||||
*
|
||||
* %Constituents contains a pointer to the Elements object, and
|
||||
* it contains wrapper functions for all of the functionality
|
||||
* of the %Elements object, i.e., atomic weights, number and identity
|
||||
* of the elements. %Elements may be added to a phase by using
|
||||
* the function Constituents::addUniqueElement(). The %Elements
|
||||
* object may be shared amongst different Phases.
|
||||
*
|
||||
* %Constituents also contains utilities retrieving the index of
|
||||
* a species in the phase given its name, Constituents::speciesIndex().
|
||||
*
|
||||
* Class State manages the independent variables of temperature, mass density,
|
||||
* and species mass/mole fraction that define the thermodynamic
|
||||
* state.
|
||||
*
|
||||
* Class %State stores just enough information about a
|
||||
* multicomponent solution to specify its intensive thermodynamic
|
||||
* state. It stores values for the temperature, mass density, and
|
||||
* an array of species mass fractions. It also stores an array of
|
||||
* species molecular weights, which are used to convert between
|
||||
* mole and mass representations of the composition. These are the
|
||||
* \e only properties of the species that class %State knows about.
|
||||
*
|
||||
* Class %State is not usually used directly in application
|
||||
* programs. Its primary use is as a base class for class
|
||||
* Phase. Class %State has no virtual methods, and none of its
|
||||
* methods are meant to be overloaded. However, this is one exception.
|
||||
* If the phase is incompressible, then the density must be replaced
|
||||
* by the pressure as the independent variable. In this case, functions
|
||||
* such as State::setMassFractions() within the class %State must actually now
|
||||
* calculate the density (at constant <I>T</I> and <I>P</I>) instead of leaving
|
||||
* it alone as befits an independent variable. Therefore, these types
|
||||
* of functions are virtual functions and need to be overloaded
|
||||
* for incompressible phases. Note, for nearly incompressible phases
|
||||
* (or phases which utilize standard states based on a <I>T</I> and <I>P</I>) this
|
||||
* change in independent variables may be advantageous as well,
|
||||
* and these functions in %State need to overload as well so that the
|
||||
* storred density within State doesn't become out of date.
|
||||
*
|
||||
* Class Phase derives from both clases
|
||||
* Constituents and State. In addition to the methods of those two
|
||||
* classes, it implements methods that allow referencing a species
|
||||
* by name. And, it contains a lot of utility functions that will
|
||||
* set the %State of the phase in its entirety, by first setting
|
||||
* the composition, then the temperature and then the density.
|
||||
* An example of this is the function,
|
||||
* Phase::setState_TRY(doublereal t, doublereal dens, const doublereal* y).
|
||||
*
|
||||
* Class Phase contains method for saving and restoring the
|
||||
* full internal states of each phase. These are called Phase::saveState()
|
||||
* and Phase::restoreState(). These functions operate on a state
|
||||
* vector, which is in general of length (2 + nSpecies()). The first
|
||||
* two entries of the state vector is temperature and density.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
//! Base class for phases of mater
|
||||
/*!
|
||||
* Base class for phases of matter. Class Phase derives from both
|
||||
* Constituents and State. In addition to the methods of those two
|
||||
* classes, it implements methods that allow referencing a species
|
||||
* by name.
|
||||
*
|
||||
* Class Phase derives from both clases
|
||||
* Constituents and State. In addition to the methods of those two
|
||||
* classes, it implements methods that allow referencing a species
|
||||
* by name. And, it contains a lot of utility functions that will
|
||||
* set the %State of the phase in its entirety, by first setting
|
||||
* the composition, then the temperature and then the density.
|
||||
* An example of this is the function,
|
||||
* Phase::setState_TRY(doublereal t, doublereal dens, const doublereal* y).
|
||||
*
|
||||
* Class Phase contains method for saving and restoring the
|
||||
* full internal states of each phase. These are called Phase::saveState()
|
||||
* and Phase::restoreState(). These functions operate on a state
|
||||
* vector, which is in general of length (2 + nSpecies()). The first
|
||||
* two entries of the state vector is temperature and density.
|
||||
*
|
||||
*
|
||||
* @todo
|
||||
* Make the concept of saving state vectors more general, so that
|
||||
* it can handle other cases where there are additional internal state
|
||||
* variables, such as the voltage, a potential energy, or a strain field.
|
||||
*
|
||||
* @ingroup phases
|
||||
*/
|
||||
class Phase : public Constituents, public State {
|
||||
|
||||
public:
|
||||
|
||||
/// Default constructor.
|
||||
Phase() : m_kk(-1), m_ndim(3), m_index(-1),
|
||||
m_xml(new XML_Node("phase")),
|
||||
m_id("<phase>"), m_name("") {}
|
||||
|
||||
/// Destructor.
|
||||
virtual ~Phase(){
|
||||
delete m_xml;
|
||||
m_xml = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy Constructor
|
||||
*
|
||||
* @param c Reference to the class to be used in the copy
|
||||
*/
|
||||
Phase(const Phase &c);
|
||||
|
||||
/**
|
||||
* Assignment operator
|
||||
*
|
||||
* @param c Reference to the class to be used in the copy
|
||||
*/
|
||||
const Phase &operator=(const Phase &c);
|
||||
|
||||
//! Returns a reference to the XML_Node storred for the phase
|
||||
/*!
|
||||
* The XML_Node for the phase contains all of the input data used
|
||||
* to set up the model for the phase, during its initialization.
|
||||
*/
|
||||
XML_Node& xml() { return *m_xml; }
|
||||
|
||||
//! Return the string id for the phase
|
||||
std::string id() const { return m_id; }
|
||||
|
||||
//! Set the string id for the phase
|
||||
/*!
|
||||
* @param id String id of the phase
|
||||
*/
|
||||
void setID(std::string id) {m_id = id;}
|
||||
|
||||
//! Return the name of the phase
|
||||
std::string name() const { return m_name; }
|
||||
|
||||
//! Sets the string name for the phase
|
||||
/*!
|
||||
* @param nm String name of the phase
|
||||
*/
|
||||
void setName(std::string nm) { m_name = nm; }
|
||||
|
||||
//! Returns the index of the phase
|
||||
int index() const { return m_index; }
|
||||
|
||||
//! Sets the index of the phase
|
||||
/*!
|
||||
* @param m Integer index of the phase
|
||||
*/
|
||||
void setIndex(int m) { m_index = m; }
|
||||
|
||||
//! Save the current internal state of the phase
|
||||
/*!
|
||||
* Write to vector 'state' the current internal state.
|
||||
*
|
||||
* @param state output vector. Will be resized to nSpecies() + 2 on return.
|
||||
*/
|
||||
void saveState(vector_fp& state) const;
|
||||
|
||||
//! Write to array 'state' the current internal state.
|
||||
/*!
|
||||
* @param lenstate length of the state array. Must be >= nSpecies() + 2
|
||||
* @param state output vector. Must be of length nSpecies() + 2 or
|
||||
* greater.
|
||||
*/
|
||||
void saveState(int lenstate, doublereal* state) const;
|
||||
|
||||
//!Restore a state saved on a previous call to saveState.
|
||||
/*!
|
||||
* @param state State vector containing the previously saved state.
|
||||
*/
|
||||
void restoreState(const vector_fp& state);
|
||||
|
||||
//! Restore the state of the phase from a previously saved state vector.
|
||||
/*!
|
||||
* @param lenstate Length of the state vector
|
||||
* @param state Vector of state conditions.
|
||||
*/
|
||||
void restoreState(int lenstate, const doublereal* state);
|
||||
|
||||
/**
|
||||
* Set the species mole fractions by name.
|
||||
* @param xMap map from species names to mole fraction values.
|
||||
* Species not listed by name in \c xMap are set to zero.
|
||||
*/
|
||||
void setMoleFractionsByName(compositionMap& xMap);
|
||||
|
||||
//! Set the mole fractions of a group of species by name
|
||||
/*!
|
||||
* The string x is in the form of a composition map
|
||||
* Species which are not listed by name in the composition
|
||||
* map are set to zero.
|
||||
*
|
||||
* @param x string x in the form of a composition map
|
||||
*/
|
||||
void setMoleFractionsByName(const std::string& x);
|
||||
|
||||
/**
|
||||
* Set the species mass fractions by name.
|
||||
* @param yMap map from species names to mass fraction values.
|
||||
* Species not listed by name in \c yMap are set to zero.
|
||||
*/
|
||||
void setMassFractionsByName(compositionMap& yMap);
|
||||
|
||||
|
||||
//! Set the species mass fractions by name.
|
||||
/*!
|
||||
* Species not listed by name in \c x are set to zero.
|
||||
*
|
||||
* @param x String containing a composition map
|
||||
*/
|
||||
void setMassFractionsByName(const std::string& x);
|
||||
|
||||
//! Set the internally storred temperature (K), density, and mole fractions.
|
||||
/*!
|
||||
* Note, the mole fractions are always set first, before the density
|
||||
*
|
||||
* @param t Temperature in kelvin
|
||||
* @param dens Density (kg/m^3)
|
||||
* @param x vector of species mole fractions.
|
||||
* Length is equal to m_kk
|
||||
*/
|
||||
void setState_TRX(doublereal t, doublereal dens, const doublereal* x);
|
||||
|
||||
|
||||
//! Set the internally storred temperature (K), density, and mole fractions.
|
||||
/*!
|
||||
* Note, the mole fractions are always set first, before the density
|
||||
*
|
||||
* @param t Temperature in kelvin
|
||||
* @param dens Density (kg/m^3)
|
||||
* @param x Composition Map containing the mole fractions.
|
||||
* Species not included in the map are assumed to have
|
||||
* a zero mole fraction.
|
||||
*/
|
||||
void setState_TRX(doublereal t, doublereal dens, compositionMap& x);
|
||||
|
||||
//! Set the internally storred temperature (K), density, and mass fractions.
|
||||
/*!
|
||||
* Note, the mass fractions are always set first, before the density
|
||||
*
|
||||
* @param t Temperature in kelvin
|
||||
* @param dens Density (kg/m^3)
|
||||
* @param y vector of species mass fractions.
|
||||
* Length is equal to m_kk
|
||||
*/
|
||||
void setState_TRY(doublereal t, doublereal dens, const doublereal* y);
|
||||
|
||||
//! Set the internally storred temperature (K), density, and mass fractions.
|
||||
/*!
|
||||
* Note, the mass fractions are always set first, before the density
|
||||
*
|
||||
* @param t Temperature in kelvin
|
||||
* @param dens Density (kg/m^3)
|
||||
* @param y Composition Map containing the mass fractions.
|
||||
* Species not included in the map are assumed to have
|
||||
* a zero mass fraction.
|
||||
*/
|
||||
void setState_TRY(doublereal t, doublereal dens, compositionMap& y);
|
||||
|
||||
//! Set the internally storred temperature (K), molar density (kmol/m^3), and mole fractions.
|
||||
/*!
|
||||
* Note, the mole fractions are always set first, before the molar density
|
||||
*
|
||||
* @param t Temperature in kelvin
|
||||
* @param n molar density (kmol/m^3)
|
||||
* @param x vector of species mole fractions.
|
||||
* Length is equal to m_kk
|
||||
*/
|
||||
void setState_TNX(doublereal t, doublereal n, const doublereal* x);
|
||||
|
||||
//! Set the internally storred temperature (K) and density (kg/m^3)
|
||||
/*!
|
||||
* @param t Temperature in kelvin
|
||||
* @param rho Density (kg/m^3)
|
||||
*/
|
||||
void setState_TR(doublereal t, doublereal rho);
|
||||
|
||||
//! Set the internally storred temperature (K) and mole fractions.
|
||||
/*!
|
||||
* @param t Temperature in kelvin
|
||||
* @param x vector of species mole fractions.
|
||||
* Length is equal to m_kk
|
||||
*/
|
||||
void setState_TX(doublereal t, doublereal* x);
|
||||
|
||||
//! Set the internally storred temperature (K) and mass fractions.
|
||||
/*!
|
||||
* @param t Temperature in kelvin
|
||||
* @param y vector of species mass fractions.
|
||||
* Length is equal to m_kk
|
||||
*/
|
||||
void setState_TY(doublereal t, doublereal* y);
|
||||
|
||||
//! Set the density (kg/m^3) and mole fractions.
|
||||
/*!
|
||||
* @param rho Density (kg/m^3)
|
||||
* @param x vector of species mole fractions.
|
||||
* Length is equal to m_kk
|
||||
*/
|
||||
void setState_RX(doublereal rho, doublereal* x);
|
||||
|
||||
//! Set the density (kg/m^3) and mass fractions.
|
||||
/*!
|
||||
* @param rho Density (kg/m^3)
|
||||
* @param y vector of species mass fractions.
|
||||
* Length is equal to m_kk
|
||||
*/
|
||||
void setState_RY(doublereal rho, doublereal* y);
|
||||
|
||||
/**
|
||||
* Copy the vector of molecular weights into vector weights.
|
||||
*
|
||||
* @param weights Output vector of molecular weights (kg/kmol)
|
||||
*/
|
||||
void getMolecularWeights(vector_fp& weights);
|
||||
|
||||
/**
|
||||
* Copy the vector of molecular weights into array weights.
|
||||
*
|
||||
* @param iwt Unused.
|
||||
* @param weights Output array of molecular weights (kg/kmol)
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
void getMolecularWeights(int iwt, doublereal* weights);
|
||||
|
||||
/**
|
||||
* Copy the vector of molecular weights into array weights.
|
||||
*
|
||||
* @param weights Output array of molecular weights (kg/kmol)
|
||||
*/
|
||||
void getMolecularWeights(doublereal* weights);
|
||||
|
||||
/**
|
||||
* Return a const reference to the internal vector of
|
||||
* molecular weights.
|
||||
*/
|
||||
const array_fp& molecularWeights();
|
||||
|
||||
/**
|
||||
* Get the mole fractions by name.
|
||||
*
|
||||
* @param x Output composition map containing the
|
||||
* species mole fractions.
|
||||
*/
|
||||
void getMoleFractionsByName(compositionMap& x);
|
||||
|
||||
//! Return the mole fraction of a single species
|
||||
/*!
|
||||
* @param k String name of the species
|
||||
*
|
||||
* @return Mole fraction of the species
|
||||
*/
|
||||
doublereal moleFraction(int k) const;
|
||||
|
||||
//! Return the mole fraction of a single species
|
||||
/*!
|
||||
* @param name String name of the species
|
||||
*
|
||||
* @return Mole fraction of the species
|
||||
*/
|
||||
doublereal moleFraction(std::string name) const;
|
||||
|
||||
//! Return the mass fraction of a single species
|
||||
/*!
|
||||
* @param k String name of the species
|
||||
*
|
||||
* @return Mass Fraction of the species
|
||||
*/
|
||||
doublereal massFraction(int k) const;
|
||||
|
||||
//! Return the mass fraction of a single species
|
||||
/*!
|
||||
* @param name String name of the species
|
||||
*
|
||||
* @return Mass Fraction of the species
|
||||
*/
|
||||
doublereal massFraction(std::string name) const;
|
||||
|
||||
/**
|
||||
* Charge density [C/m^3].
|
||||
*/
|
||||
doublereal chargeDensity() const;
|
||||
|
||||
/// Returns the number of spatial dimensions (1, 2, or 3)
|
||||
int nDim() {return m_ndim;}
|
||||
|
||||
//! Set the number of spatial dimensions (1, 2, or 3)
|
||||
/*!
|
||||
* The number of spatial dimensions is used for vector involving
|
||||
* directions.
|
||||
*
|
||||
* @param ndim Input number of dimensions.
|
||||
*/
|
||||
void setNDim(int ndim) {m_ndim = ndim;}
|
||||
|
||||
/**
|
||||
* Finished adding species, prepare to use them for calculation
|
||||
* of mixture properties.
|
||||
*/
|
||||
virtual void freezeSpecies();
|
||||
|
||||
virtual bool ready() const;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* m_kk = Number of species in the phase. @internal m_kk is a
|
||||
* member of both the State and Constituents classes.
|
||||
* Therefore, to avoid multiple inheritance problems, we need
|
||||
* to restate it in here, so that the declarations in the two
|
||||
* base classes become hidden.
|
||||
*/
|
||||
int m_kk;
|
||||
/**
|
||||
* m_ndim is the dimensionality of the phase. Volumetric
|
||||
* phases have dimensionality 3 and surface phases have
|
||||
* dimensionality 2.
|
||||
*/
|
||||
int m_ndim;
|
||||
/**
|
||||
* m_index is the index of the phase
|
||||
*
|
||||
*/
|
||||
int m_index;
|
||||
|
||||
private:
|
||||
|
||||
//! This stores the initial state of the system
|
||||
/*!
|
||||
* @deprecated
|
||||
* This doesn't seem to be used much anymore.
|
||||
*/
|
||||
vector_fp m_data;
|
||||
|
||||
//! Pointer to the XML node containing the XML info for this phase
|
||||
XML_Node* m_xml;
|
||||
|
||||
//! ID of the phase.
|
||||
/*!
|
||||
* This is the value of the ID attribute of the XML phase node.
|
||||
*/
|
||||
std::string m_id;
|
||||
|
||||
//! Name of the phase.
|
||||
/*!
|
||||
* Initially, this is the value of the ID attribute of the XML phase node.
|
||||
*/
|
||||
std::string m_name;
|
||||
};
|
||||
|
||||
//! typedef for the base Phase class
|
||||
typedef Phase phase_t;
|
||||
}
|
||||
|
||||
#endif
|
||||
253
Cantera/src/thermo/PureFluidPhase.cpp
Normal file
253
Cantera/src/thermo/PureFluidPhase.cpp
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
/**
|
||||
* @file PureFluidPhase.cpp
|
||||
* Definitions for a ThermoPhase object for a pure fluid phase consisting of gas, liquid, mixed-gas-liquid
|
||||
* and supercritical fluid (see \ref thermoprops
|
||||
* and class \link Cantera::PureFluidPhase PureFluidPhase\endlink).
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
#include "xml.h"
|
||||
#include "PureFluidPhase.h"
|
||||
|
||||
#include "../../../ext/tpx/Sub.h"
|
||||
#include "../../../ext/tpx/utils.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
PureFluidPhase::~PureFluidPhase() { delete m_sub; }
|
||||
|
||||
void PureFluidPhase::
|
||||
initThermo() {
|
||||
if (m_sub) delete m_sub;
|
||||
m_sub = tpx::GetSub(m_subflag);
|
||||
if (m_sub == 0) {
|
||||
throw CanteraError("PureFluidPhase::initThermo",
|
||||
"could not create new substance object.");
|
||||
}
|
||||
m_mw = m_sub->MolWt();
|
||||
m_weight[0] = m_mw;
|
||||
setMolecularWeight(0,m_mw);
|
||||
double one = 1.0;
|
||||
setMoleFractions(&one);
|
||||
double cp0_R, h0_RT, s0_R, T0, p;
|
||||
T0 = 298.15;
|
||||
if (T0 < m_sub->Tcrit()) {
|
||||
m_sub->Set(tpx::TX, T0, 1.0);
|
||||
p = 0.01*m_sub->P();
|
||||
}
|
||||
else {
|
||||
p = 0.001*m_sub->Pcrit();
|
||||
}
|
||||
m_sub->Set(tpx::TP, T0, p);
|
||||
|
||||
m_spthermo->update_one(0, T0, &cp0_R, &h0_RT, &s0_R);
|
||||
double s_R = s0_R - log(p/refPressure());
|
||||
m_sub->setStdState(h0_RT*GasConstant*298.15/m_mw,
|
||||
s_R*GasConstant/m_mw, T0, p);
|
||||
if (m_verbose) {
|
||||
writelog("PureFluidPhase::initThermo: initialized phase "
|
||||
+id()+"\n");
|
||||
}
|
||||
}
|
||||
|
||||
void PureFluidPhase::
|
||||
setParametersFromXML(const XML_Node& eosdata) {
|
||||
eosdata._require("model","PureFluid");
|
||||
m_subflag = atoi(eosdata["fluid_type"].c_str());
|
||||
if (m_subflag < 0)
|
||||
throw CanteraError("PureFluidPhase::setParametersFromXML",
|
||||
"missing or negative substance flag");
|
||||
}
|
||||
|
||||
doublereal PureFluidPhase::
|
||||
enthalpy_mole() const {
|
||||
setTPXState();
|
||||
doublereal h = m_sub->h() * m_mw;
|
||||
check(h);
|
||||
return h;
|
||||
}
|
||||
|
||||
doublereal PureFluidPhase::
|
||||
intEnergy_mole() const {
|
||||
setTPXState();
|
||||
doublereal u = m_sub->u() * m_mw;
|
||||
check(u);
|
||||
return u;
|
||||
}
|
||||
|
||||
doublereal PureFluidPhase::
|
||||
entropy_mole() const {
|
||||
setTPXState();
|
||||
doublereal s = m_sub->s() * m_mw;
|
||||
check(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
doublereal PureFluidPhase::
|
||||
gibbs_mole() const {
|
||||
setTPXState();
|
||||
doublereal g = m_sub->g() * m_mw;
|
||||
check(g);
|
||||
return g;
|
||||
}
|
||||
|
||||
doublereal PureFluidPhase::
|
||||
cp_mole() const {
|
||||
setTPXState();
|
||||
doublereal cp = m_sub->cp() * m_mw;
|
||||
check(cp);
|
||||
return cp;
|
||||
}
|
||||
|
||||
doublereal PureFluidPhase::
|
||||
cv_mole() const {
|
||||
setTPXState();
|
||||
doublereal cv = m_sub->cv() * m_mw;
|
||||
check(cv);
|
||||
return cv;
|
||||
}
|
||||
|
||||
doublereal PureFluidPhase::
|
||||
pressure() const {
|
||||
setTPXState();
|
||||
doublereal p = m_sub->P();
|
||||
check(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
void PureFluidPhase::
|
||||
setPressure(doublereal p) {
|
||||
Set(tpx::TP, temperature(), p);
|
||||
setDensity(1.0/m_sub->v());
|
||||
check();
|
||||
}
|
||||
|
||||
void PureFluidPhase::Set(int n, double x, double y) const {
|
||||
try {
|
||||
m_sub->Set(n, x, y);
|
||||
}
|
||||
catch(tpx::TPX_Error) {
|
||||
reportTPXError();
|
||||
}
|
||||
}
|
||||
|
||||
void PureFluidPhase::setTPXState() const {
|
||||
Set(tpx::TV, temperature(), 1.0/density());
|
||||
}
|
||||
|
||||
void PureFluidPhase::check(doublereal v) const {
|
||||
if (m_sub->Error() || v == tpx::Undef) {
|
||||
throw CanteraError("PureFluidPhase",string(tpx::errorMsg(
|
||||
m_sub->Error())));
|
||||
}
|
||||
}
|
||||
|
||||
void PureFluidPhase::reportTPXError() const {
|
||||
string msg = tpx::TPX_Error::ErrorMessage;
|
||||
string proc = "tpx::"+tpx::TPX_Error::ErrorProcedure;
|
||||
throw CanteraError(proc,msg);
|
||||
}
|
||||
|
||||
|
||||
doublereal PureFluidPhase::isothermalCompressibility() const {
|
||||
return m_sub->isothermalCompressibility();
|
||||
}
|
||||
|
||||
doublereal PureFluidPhase::thermalExpansionCoeff() const {
|
||||
return m_sub->thermalExpansionCoeff();
|
||||
}
|
||||
|
||||
tpx::Substance& PureFluidPhase::TPX_Substance() { return *m_sub; }
|
||||
|
||||
/// critical temperature
|
||||
doublereal PureFluidPhase::critTemperature() const { return m_sub->Tcrit(); }
|
||||
|
||||
/// critical pressure
|
||||
doublereal PureFluidPhase::critPressure() const { return m_sub->Pcrit(); }
|
||||
|
||||
/// critical density
|
||||
doublereal PureFluidPhase::critDensity() const { return 1.0/m_sub->Vcrit(); }
|
||||
|
||||
|
||||
/// saturation temperature
|
||||
doublereal PureFluidPhase::satTemperature(doublereal p) const {
|
||||
try {
|
||||
doublereal ts = m_sub->Tsat(p);
|
||||
return ts;
|
||||
}
|
||||
catch(tpx::TPX_Error) {
|
||||
reportTPXError();
|
||||
return -1.0;
|
||||
}
|
||||
}
|
||||
|
||||
void PureFluidPhase::setState_HP(doublereal h, doublereal p,
|
||||
doublereal tol) {
|
||||
Set(tpx::HP, h, p);
|
||||
setState_TR(m_sub->Temp(), 1.0/m_sub->v());
|
||||
check();
|
||||
}
|
||||
|
||||
void PureFluidPhase::setState_UV(doublereal u, doublereal v,
|
||||
doublereal tol) {
|
||||
Set(tpx::UV, u, v);
|
||||
setState_TR(m_sub->Temp(), 1.0/m_sub->v());
|
||||
check();
|
||||
}
|
||||
|
||||
void PureFluidPhase::setState_SV(doublereal s, doublereal v,
|
||||
doublereal tol) {
|
||||
Set(tpx::SV, s, v);
|
||||
setState_TR(m_sub->Temp(), 1.0/m_sub->v());
|
||||
check();
|
||||
}
|
||||
|
||||
void PureFluidPhase::setState_SP(doublereal s, doublereal p,
|
||||
doublereal tol) {
|
||||
Set(tpx::SP, s, p);
|
||||
setState_TR(m_sub->Temp(), 1.0/m_sub->v());
|
||||
check();
|
||||
}
|
||||
|
||||
/// saturation pressure
|
||||
doublereal PureFluidPhase::satPressure(doublereal t) const {
|
||||
doublereal vsv = m_sub->v();
|
||||
try {
|
||||
Set(tpx::TV,t,vsv);
|
||||
doublereal ps = m_sub->Ps();
|
||||
return ps;
|
||||
}
|
||||
catch(tpx::TPX_Error) {
|
||||
reportTPXError();
|
||||
return -1.0;
|
||||
}
|
||||
}
|
||||
|
||||
doublereal PureFluidPhase::vaporFraction() const {
|
||||
setTPXState();
|
||||
doublereal x = m_sub->x();
|
||||
check(x);
|
||||
return x;
|
||||
}
|
||||
|
||||
void PureFluidPhase::setState_Tsat(doublereal t, doublereal x) {
|
||||
setTemperature(t);
|
||||
setTPXState();
|
||||
Set(tpx::TX, t, x);
|
||||
setDensity(1.0/m_sub->v());
|
||||
check();
|
||||
}
|
||||
|
||||
void PureFluidPhase::setState_Psat(doublereal p, doublereal x) {
|
||||
setTPXState();
|
||||
Set(tpx::PX, p, x);
|
||||
setTemperature(m_sub->Temp());
|
||||
setDensity(1.0/m_sub->v());
|
||||
check();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
317
Cantera/src/thermo/PureFluidPhase.h
Normal file
317
Cantera/src/thermo/PureFluidPhase.h
Normal file
|
|
@ -0,0 +1,317 @@
|
|||
/**
|
||||
* @file PureFluidPhase.h
|
||||
* Header for a ThermoPhase object for a pure fluid phase consisting of gas, liquid, mixed-gas-liquid
|
||||
* and supercrit fluid (see \ref thermoprops
|
||||
* and class \link Cantera::PureFluidPhase PureFluidPhase\endlink).
|
||||
*
|
||||
*
|
||||
* This object is only available if the WITH_PURE_FLUIDS optional compile
|
||||
* capability has been turned on in Cantera's makefile system.
|
||||
* It inherits from ThermoPhase, but is built on top of the tpx package.
|
||||
*/
|
||||
|
||||
/* $Author$
|
||||
* $Date$
|
||||
* $Revision$
|
||||
*
|
||||
* Copyright 2003 California Institute of Technology
|
||||
*/
|
||||
|
||||
#ifndef CT_EOS_TPX_H
|
||||
#define CT_EOS_TPX_H
|
||||
|
||||
#include "ThermoPhase.h"
|
||||
|
||||
/**
|
||||
* This object is only available if the WITH_PURE_FLUIDS optional compile
|
||||
* capability has been turned on in Cantera's makefile system.
|
||||
*/
|
||||
#ifdef WITH_PURE_FLUIDS
|
||||
|
||||
#include "mix_defs.h"
|
||||
|
||||
namespace tpx {
|
||||
class Substance;
|
||||
}
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
//! This phase object consists of a single component that can be a gas, a liquid,
|
||||
//! a mixed gas-liquid fluid, or a fluid beyond its critical point
|
||||
/*!
|
||||
* The object inherits from ThermoPhase. However, its build on top of the
|
||||
* tpx package.
|
||||
*
|
||||
*
|
||||
* <H2> Specification of Species Standard State Properties </H2>
|
||||
*
|
||||
*
|
||||
* <H2> Application within %Kinetics Managers </H2>
|
||||
*
|
||||
*
|
||||
* <H2> XML Example </H2>
|
||||
*
|
||||
*
|
||||
* <H2> Instantiation of the Class </H2>
|
||||
*
|
||||
* @ingroup thermoprops
|
||||
*/
|
||||
class PureFluidPhase : public ThermoPhase {
|
||||
|
||||
public:
|
||||
|
||||
//! Base Constructor
|
||||
PureFluidPhase() : ThermoPhase(), m_sub(0), m_subflag(0),
|
||||
m_mw(-1.0), m_verbose(false) {}
|
||||
|
||||
//! Destructor
|
||||
virtual ~PureFluidPhase();
|
||||
|
||||
//! Equation of state type
|
||||
virtual int eosType() const { return cPureFluid; }
|
||||
|
||||
/// Molar enthalpy. Units: J/kmol.
|
||||
virtual doublereal enthalpy_mole() const;
|
||||
|
||||
/// Molar internal energy. Units: J/kmol.
|
||||
virtual doublereal intEnergy_mole() const;
|
||||
|
||||
/// Molar entropy. Units: J/kmol/K.
|
||||
virtual doublereal entropy_mole() const;
|
||||
|
||||
/// Molar Gibbs function. Units: J/kmol.
|
||||
virtual doublereal gibbs_mole() const;
|
||||
|
||||
/// Molar heat capacity at constant pressure. Units: J/kmol/K.
|
||||
virtual doublereal cp_mole() const;
|
||||
|
||||
/// Molar heat capacity at constant volume. Units: J/kmol/K.
|
||||
virtual doublereal cv_mole() const;
|
||||
|
||||
//! Return the thermodynamic pressure (Pa).
|
||||
/*!
|
||||
* This method calculates the current pressure consistent with the
|
||||
* independent variables, T, rho.
|
||||
*/
|
||||
virtual doublereal pressure() const;
|
||||
|
||||
//! sets the thermodynamic pressure (Pa).
|
||||
/*!
|
||||
* This method calculates the density that is consistent with the
|
||||
* desired pressure, given the temperature.
|
||||
*
|
||||
* @param p Pressure (Pa)
|
||||
*/
|
||||
virtual void setPressure(doublereal p);
|
||||
|
||||
//! Get the species chemical potentials. Units: J/kmol.
|
||||
/*!
|
||||
* This function returns a vector of chemical potentials of the
|
||||
* species in solution at the current temperature, pressure
|
||||
* and mole fraction of the solution.
|
||||
*
|
||||
* @param mu Output vector of species chemical
|
||||
* potentials. Length: m_kk. Units: J/kmol
|
||||
*/
|
||||
virtual void getChemPotentials(doublereal* mu) const {
|
||||
mu[0] = gibbs_mole();
|
||||
}
|
||||
|
||||
//! Returns the isothermal compressibility. Units: 1/Pa.
|
||||
/*!
|
||||
* The isothermal compressibility is defined as
|
||||
* \f[
|
||||
* \kappa_T = -\frac{1}{v}\left(\frac{\partial v}{\partial P}\right)_T
|
||||
* \f]
|
||||
*/
|
||||
virtual doublereal isothermalCompressibility() const;
|
||||
|
||||
//! Return the volumetric thermal expansion coefficient. Units: 1/K.
|
||||
/*!
|
||||
* The thermal expansion coefficient is defined as
|
||||
* \f[
|
||||
* \beta = \frac{1}{v}\left(\frac{\partial v}{\partial T}\right)_P
|
||||
* \f]
|
||||
*/
|
||||
virtual doublereal thermalExpansionCoeff() const;
|
||||
|
||||
//! Returns a reference to the substance object
|
||||
tpx::Substance& TPX_Substance();
|
||||
|
||||
/// critical temperature
|
||||
virtual doublereal critTemperature() const;
|
||||
|
||||
/// critical pressure
|
||||
virtual doublereal critPressure() const;
|
||||
|
||||
/// critical density
|
||||
virtual doublereal critDensity() const;
|
||||
|
||||
/// saturation temperature
|
||||
/*!
|
||||
* @param p Pressure (Pa)
|
||||
*/
|
||||
virtual doublereal satTemperature(doublereal p) const;
|
||||
|
||||
//! Set the internally storred specific enthalpy (J/kg) and pressure (Pa) of the phase.
|
||||
/*!
|
||||
* @param h Specific enthalpy (J/kg)
|
||||
* @param p Pressure (Pa)
|
||||
* @param tol Optional parameter setting the tolerance of the
|
||||
* calculation.
|
||||
*/
|
||||
virtual void setState_HP(doublereal h, doublereal p,
|
||||
doublereal tol = 1.e-8);
|
||||
|
||||
//! Set the specific internal energy (J/kg) and specific volume (m^3/kg).
|
||||
/*!
|
||||
* This function fixes the internal state of the phase so that
|
||||
* the specific internal energy and specific volume have the value of the input parameters.
|
||||
*
|
||||
* @param u specific internal energy (J/kg)
|
||||
* @param v specific volume (m^3/kg).
|
||||
* @param tol Optional parameter setting the tolerance of the
|
||||
* calculation.
|
||||
*/
|
||||
virtual void setState_UV(doublereal u, doublereal v,
|
||||
doublereal tol = 1.e-8);
|
||||
|
||||
//! Set the specific entropy (J/kg/K) and specific volume (m^3/kg).
|
||||
/*!
|
||||
* This function fixes the internal state of the phase so that
|
||||
* the specific entropy and specific volume have the value of the input parameters.
|
||||
*
|
||||
* @param s specific entropy (J/kg/K)
|
||||
* @param v specific volume (m^3/kg).
|
||||
* @param tol Optional parameter setting the tolerance of the
|
||||
* calculation.
|
||||
*/
|
||||
virtual void setState_SV(doublereal s, doublereal v,
|
||||
doublereal tol = 1.e-8);
|
||||
|
||||
//! Set the specific entropy (J/kg/K) and pressure (Pa).
|
||||
/*!
|
||||
* This function fixes the internal state of the phase so that
|
||||
* the specific entropy and the pressure have the value of the input parameters.
|
||||
*
|
||||
* @param s specific entropy (J/kg/K)
|
||||
* @param p specific pressure (Pa).
|
||||
* @param tol Optional parameter setting the tolerance of the
|
||||
* calculation.
|
||||
*/
|
||||
virtual void setState_SP(doublereal s, doublereal p,
|
||||
doublereal tol = 1.e-8);
|
||||
|
||||
|
||||
|
||||
//! @name Saturation properties.
|
||||
/*!
|
||||
* These methods are only implemented by subclasses that
|
||||
* implement full liquid-vapor equations of state. They may be
|
||||
* moved out of ThermoPhase at a later date.
|
||||
*/
|
||||
//@{
|
||||
|
||||
//! Return the saturation pressure given the temperatur
|
||||
/*!
|
||||
* @param t Temperature (Kelvin)
|
||||
*/
|
||||
virtual doublereal satPressure(doublereal t) const;
|
||||
|
||||
//! Return the fraction of vapor at the current conditions
|
||||
virtual doublereal vaporFraction() const;
|
||||
|
||||
//! Set the state to a saturated system at a particular temperature
|
||||
/*!
|
||||
* @param t Temperature (kelvin)
|
||||
* @param x Fraction of vapor
|
||||
*/
|
||||
virtual void setState_Tsat(doublereal t, doublereal x);
|
||||
|
||||
//! Set the state to a saturated system at a particular pressure
|
||||
/*!
|
||||
* @param p Pressure (Pa)
|
||||
* @param x Fraction of vapor
|
||||
*/
|
||||
virtual void setState_Psat(doublereal p, doublereal x);
|
||||
//@}
|
||||
|
||||
//! Initialize the ThermoPhase object after all species have been set up
|
||||
/*!
|
||||
* @internal Initialize.
|
||||
*
|
||||
* This method is provided to allow
|
||||
* subclasses to perform any initialization required after all
|
||||
* species have been added. For example, it might be used to
|
||||
* resize internal work arrays that must have an entry for
|
||||
* each species. The base class implementation does nothing,
|
||||
* and subclasses that do not require initialization do not
|
||||
* need to overload this method. When importing a CTML phase
|
||||
* description, this method is called from ThermoPhase::initThermoXML(),
|
||||
* which is called from importPhase(),
|
||||
* just prior to returning from function importPhase().
|
||||
*
|
||||
* @see importCTML.cpp
|
||||
*/
|
||||
virtual void initThermo();
|
||||
|
||||
//! Set equation of state parameter values from XML entries.
|
||||
/*!
|
||||
*
|
||||
* This method is called by function importPhase() in
|
||||
* file importCTML.cpp when processing a phase definition in
|
||||
* an input file. It should be overloaded in subclasses to set
|
||||
* any parameters that are specific to that particular phase
|
||||
* model. Note, this method is called before the phase is
|
||||
* initialzed with elements and/or species.
|
||||
*
|
||||
* @param eosdata An XML_Node object corresponding to
|
||||
* the "thermo" entry for this phase in the input file.
|
||||
*/
|
||||
virtual void setParametersFromXML(const XML_Node& eosdata);
|
||||
|
||||
protected:
|
||||
|
||||
//! Main call to the tpx level to set the state of the system
|
||||
/*!
|
||||
* @param n Integer indicating which 2 thermo components are held constant
|
||||
* @param x Value of the first component
|
||||
* @param y Value of the second component
|
||||
*/
|
||||
void Set(int n, double x, double y) const;
|
||||
|
||||
//! Sets the state using a TPX::TV call
|
||||
void setTPXState() const;
|
||||
|
||||
//! Carry out a internal check on tpx, it may have thrown an error.
|
||||
/*!
|
||||
* @param v Defaults to zero
|
||||
*/
|
||||
void check(doublereal v = 0.0) const;
|
||||
|
||||
//! Report errors in the TPX level
|
||||
void reportTPXError() const;
|
||||
|
||||
private:
|
||||
|
||||
//! Pointer to the underlying tpx object Substance that does the work
|
||||
mutable tpx::Substance* m_sub;
|
||||
|
||||
//! Int indicating the type of the fluid
|
||||
/*!
|
||||
* The tpx package uses an int to indicate what fluid is being sought.
|
||||
*/
|
||||
int m_subflag;
|
||||
|
||||
//! Molecular weight of the substance (kg kmol-1)
|
||||
doublereal m_mw;
|
||||
|
||||
//! flag to turn on some printing.
|
||||
bool m_verbose;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
594
Cantera/src/thermo/ShomatePoly.h
Executable file
594
Cantera/src/thermo/ShomatePoly.h
Executable file
|
|
@ -0,0 +1,594 @@
|
|||
/**
|
||||
* @file ShomatePoly.h
|
||||
* Header for a single-species standard state object derived
|
||||
* from \link Cantera::SpeciesThermoInterpType SpeciesThermoInterpType\endlink based
|
||||
* on the Shomate temperature polynomial form applied to one temperature region
|
||||
* (see \ref spthermo and class \link Cantera::ShomatePoly ShomatePoly\endlink and
|
||||
* \link Cantera::ShomatePoly2 ShomatePoly2\endlink).
|
||||
* Shomate polynomial expressions.
|
||||
*/
|
||||
/*
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
// Copyright 2001 California Institute of Technology
|
||||
|
||||
|
||||
#ifndef CT_SHOMATEPOLY1_H
|
||||
#define CT_SHOMATEPOLY1_H
|
||||
|
||||
#include "SpeciesThermoInterpType.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
|
||||
//! The Shomate polynomial parameterization for one temperature range
|
||||
//! for one species
|
||||
/*!
|
||||
*
|
||||
* Seven coefficients \f$(A,\dots,G)\f$ are used to represent
|
||||
* \f$ c_p^0(T)\f$, \f$ h^0(T)\f$, and \f$ s^0(T) \f$ as
|
||||
* polynomials in the temperature, \f$ T \f$ :
|
||||
*
|
||||
* \f[
|
||||
* \tilde{c}_p^0(T) = A + B t + C t^2 + D t^3 + \frac{E}{t^2}
|
||||
* \f]
|
||||
* \f[
|
||||
* \tilde{h}^0(T) = A t + \frac{B t^2}{2} + \frac{C t^3}{3}
|
||||
+ \frac{D t^4}{4} - \frac{E}{t} + F.
|
||||
* \f]
|
||||
* \f[
|
||||
* \tilde{s}^0(T) = A\ln t + B t + \frac{C t^2}{2}
|
||||
+ \frac{D t^3}{3} - \frac{E}{2t^2} + G.
|
||||
* \f]
|
||||
*
|
||||
* In the above expressions, the thermodynamic polynomials are expressed
|
||||
* in dimensional units, but the temperature,\f$ t \f$, is divided by 1000. The
|
||||
* following dimensions are assumed in the above expressions:
|
||||
*
|
||||
* - \f$ \tilde{c}_p^0(T)\f$ = Heat Capacity (J/gmol*K)
|
||||
* - \f$ \tilde{h}^0(T) \f$ = standard Enthalpy (kJ/gmol)
|
||||
* - \f$ \tilde{s}^0(T) \f$= standard Entropy (J/gmol*K)
|
||||
* - \f$ t \f$= temperature (K) / 1000.
|
||||
*
|
||||
* For more information about Shomate polynomials, see the NIST website,
|
||||
* http://webbook.nist.gov/
|
||||
*
|
||||
* Before being used within Cantera, the dimensions must be adjusted to those
|
||||
* used by Cantera (i.e., Joules and kmol).
|
||||
*
|
||||
|
||||
* @ingroup spthermo
|
||||
*/
|
||||
class ShomatePoly : public SpeciesThermoInterpType {
|
||||
|
||||
public:
|
||||
|
||||
//! Empty constructor
|
||||
ShomatePoly()
|
||||
: m_lowT(0.0), m_highT (0.0),
|
||||
m_Pref(0.0), m_index (0) {}
|
||||
|
||||
//! Constructor used in templated instantiations
|
||||
/*!
|
||||
* @param n Species index
|
||||
* @param tlow Minimum temperature
|
||||
* @param thigh Maximum temperature
|
||||
* @param pref reference pressure (Pa).
|
||||
* @param coeffs Vector of coefficients used to set the
|
||||
* parameters for the standard state for species n.
|
||||
* There are 7 coefficients for the Shomate polynomial:
|
||||
* - c[0] = \f$ A \f$
|
||||
* - c[1] = \f$ B \f$
|
||||
* - c[2] = \f$ C \f$
|
||||
* - c[3] = \f$ D \f$
|
||||
* - c[4] = \f$ E \f$
|
||||
* - c[5] = \f$ F \f$
|
||||
* - c[6] = \f$ G \f$
|
||||
*
|
||||
* See the class description for the polynomial representation of the
|
||||
* thermo functions in terms of \f$ A, \dots, G \f$.
|
||||
*/
|
||||
ShomatePoly(int n, doublereal tlow, doublereal thigh, doublereal pref,
|
||||
const doublereal* coeffs) :
|
||||
m_lowT (tlow),
|
||||
m_highT (thigh),
|
||||
m_Pref (pref),
|
||||
m_index (n) {
|
||||
m_coeff.resize(7);
|
||||
std::copy(coeffs, coeffs + 7, m_coeff.begin());
|
||||
}
|
||||
|
||||
//! copy constructor
|
||||
/*!
|
||||
* @param b object to be copied
|
||||
*/
|
||||
ShomatePoly(const ShomatePoly& b) :
|
||||
m_lowT (b.m_lowT),
|
||||
m_highT (b.m_highT),
|
||||
m_Pref (b.m_Pref),
|
||||
m_coeff (array_fp(7)),
|
||||
m_index (b.m_index) {
|
||||
std::copy(b.m_coeff.begin(),
|
||||
b.m_coeff.begin() + 7,
|
||||
m_coeff.begin());
|
||||
}
|
||||
|
||||
//! Assignment operator
|
||||
/*!
|
||||
* @param b
|
||||
*/
|
||||
ShomatePoly& operator=(const ShomatePoly& b) {
|
||||
if (&b != this) {
|
||||
m_lowT = b.m_lowT;
|
||||
m_highT = b.m_highT;
|
||||
m_Pref = b.m_Pref;
|
||||
m_index = b.m_index;
|
||||
m_coeff.resize(7);
|
||||
std::copy(b.m_coeff.begin(),
|
||||
b.m_coeff.begin() + 7,
|
||||
m_coeff.begin());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
virtual ~ShomatePoly(){}
|
||||
|
||||
//! Duplicator from the base class
|
||||
virtual SpeciesThermoInterpType *
|
||||
duplMyselfAsSpeciesThermoInterpType() const {
|
||||
ShomatePoly* sp = new ShomatePoly(*this);
|
||||
return (SpeciesThermoInterpType *) sp;
|
||||
}
|
||||
|
||||
//! Returns the minimum temperature that the thermo
|
||||
//! parameterization is valid
|
||||
virtual doublereal minTemp() const { return m_lowT;}
|
||||
|
||||
//! Returns the maximum temperature that the thermo
|
||||
//! parameterization is valid
|
||||
virtual doublereal maxTemp() const { return m_highT;}
|
||||
|
||||
//! Returns the reference pressure (Pa)
|
||||
virtual doublereal refPressure() const { return m_Pref; }
|
||||
|
||||
//! Returns an integer representing the type of parameterization
|
||||
virtual int reportType() const { return SHOMATE; }
|
||||
|
||||
|
||||
//! Update the properties for this species, given a temperature polynomial
|
||||
/*!
|
||||
* This method is called with a pointer to an array containing the functions of
|
||||
* temperature needed by this parameterization, and three pointers to arrays where the
|
||||
* computed property values should be written. This method updates only one value in
|
||||
* each array.
|
||||
*
|
||||
* tt is T/1000.
|
||||
* m_t[0] = tt;
|
||||
* m_t[1] = tt*tt;
|
||||
* m_t[2] = m_t[1]*tt;
|
||||
* m_t[3] = 1.0/m_t[1];
|
||||
* m_t[4] = log(tt);
|
||||
* m_t[5] = 1.0/GasConstant;
|
||||
* m_t[6] = 1.0/(GasConstant * T);
|
||||
*
|
||||
* @param tt Vector of temperature polynomials
|
||||
* @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).
|
||||
*/
|
||||
virtual void updateProperties(const doublereal* tt,
|
||||
doublereal* cp_R, doublereal* h_RT,
|
||||
doublereal* s_R) const {
|
||||
|
||||
doublereal A = m_coeff[0];
|
||||
doublereal Bt = m_coeff[1]*tt[0];
|
||||
doublereal Ct2 = m_coeff[2]*tt[1];
|
||||
doublereal Dt3 = m_coeff[3]*tt[2];
|
||||
doublereal Etm2 = m_coeff[4]*tt[3];
|
||||
doublereal F = m_coeff[5];
|
||||
doublereal G = m_coeff[6];
|
||||
|
||||
doublereal cp, h, s;
|
||||
cp = A + Bt + Ct2 + Dt3 + Etm2;
|
||||
h = tt[0]*(A + 0.5*Bt + OneThird*Ct2 + 0.25*Dt3 - Etm2) + F;
|
||||
s = A*tt[4] + Bt + 0.5*Ct2 + OneThird*Dt3 - 0.5*Etm2 + G;
|
||||
|
||||
/*
|
||||
* Shomate polynomials parameterizes assuming units of
|
||||
* J/(gmol*K) for cp_r and s_R and kJ/(gmol) for h.
|
||||
* However, Cantera assumes default MKS units of
|
||||
* J/(kmol*K). This requires us to multiply cp and s
|
||||
* by 1.e3 and h by 1.e6, before we then nondimensionlize
|
||||
* the results by dividing by (GasConstant * T),
|
||||
* where GasConstant has units of J/(kmol * K).
|
||||
*/
|
||||
cp_R[m_index] = 1.e3 * cp * tt[5];
|
||||
h_RT[m_index] = 1.e6 * h * tt[6];
|
||||
s_R[m_index] = 1.e3 * s * tt[5];
|
||||
}
|
||||
|
||||
//! Compute the reference-state property of one species
|
||||
/*!
|
||||
* Given temperature T in K, this method updates the values of
|
||||
* the non-dimensional heat capacity at constant pressure,
|
||||
* enthalpy, and entropy, at the reference pressure, Pref
|
||||
* of one of the species. The species index is used
|
||||
* to reference into the cp_R, h_RT, and s_R arrays.
|
||||
*
|
||||
* @param temp 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).
|
||||
*/
|
||||
virtual void updatePropertiesTemp(const doublereal temp,
|
||||
doublereal* cp_R, doublereal* h_RT,
|
||||
doublereal* s_R) const {
|
||||
double tPoly[7];
|
||||
doublereal tt = 1.e-3*temp;
|
||||
tPoly[0] = tt;
|
||||
tPoly[1] = tt * tt;
|
||||
tPoly[2] = tPoly[1] * tt;
|
||||
tPoly[3] = 1.0/tPoly[1];
|
||||
tPoly[4] = std::log(tt);
|
||||
tPoly[5] = 1.0/GasConstant;
|
||||
tPoly[6] = 1.0/(GasConstant * temp);
|
||||
updateProperties(tPoly, cp_R, h_RT, s_R);
|
||||
}
|
||||
|
||||
//!This utility function reports back the type of
|
||||
//! parameterization and all of the parameters for the
|
||||
//! species, index.
|
||||
/*!
|
||||
* All parameters are output variables
|
||||
*
|
||||
* @param n Species index
|
||||
* @param type Integer type of the standard type
|
||||
* @param tlow output - Minimum temperature
|
||||
* @param thigh output - Maximum temperature
|
||||
* @param pref output - reference pressure (Pa).
|
||||
* @param coeffs Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
*/
|
||||
virtual void reportParameters(int &n, int &type,
|
||||
doublereal &tlow, doublereal &thigh,
|
||||
doublereal &pref,
|
||||
doublereal* const coeffs) const {
|
||||
n = m_index;
|
||||
type = SHOMATE;
|
||||
tlow = m_lowT;
|
||||
thigh = m_highT;
|
||||
pref = m_Pref;
|
||||
for (int i = 0; i < 7; i++) {
|
||||
coeffs[i] = m_coeff[i];
|
||||
}
|
||||
}
|
||||
|
||||
//! Modify parameters for the standard state
|
||||
/*!
|
||||
* @param coeffs Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
*/
|
||||
virtual void modifyParameters(doublereal* coeffs) {
|
||||
if (m_coeff.size() != 7) {
|
||||
throw CanteraError("modifyParameters",
|
||||
"modifying something that hasn't been initialized");
|
||||
}
|
||||
std::copy(coeffs, coeffs + 7, m_coeff.begin());
|
||||
}
|
||||
|
||||
protected:
|
||||
//! Minimum temperature for which the parameterization is valid (Kelvin)
|
||||
doublereal m_lowT;
|
||||
//! Maximum temperature for which the parameterization is valid (Kelvin)
|
||||
doublereal m_highT;
|
||||
//! Reference pressure (Pa)
|
||||
doublereal m_Pref;
|
||||
//! Array of coeffcients
|
||||
array_fp m_coeff;
|
||||
//! Species Index
|
||||
int m_index;
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
//! The Shomate polynomial parameterization for two temperature ranges
|
||||
//! for one species
|
||||
/*!
|
||||
*
|
||||
* Seven coefficients \f$(A,\dots,G)\f$ are used to represent
|
||||
* \f$ c_p^0(T)\f$, \f$ h^0(T)\f$, and \f$ s^0(T) \f$ as
|
||||
* polynomials in the temperature, \f$ T \f$, in one temperature region:
|
||||
*
|
||||
* \f[
|
||||
* \tilde{c}_p^0(T) = A + B t + C t^2 + D t^3 + \frac{E}{t^2}
|
||||
* \f]
|
||||
* \f[
|
||||
* \tilde{h}^0(T) = A t + \frac{B t^2}{2} + \frac{C t^3}{3}
|
||||
+ \frac{D t^4}{4} - \frac{E}{t} + F.
|
||||
* \f]
|
||||
* \f[
|
||||
* \tilde{s}^0(T) = A\ln t + B t + \frac{C t^2}{2}
|
||||
+ \frac{D t^3}{3} - \frac{E}{2t^2} + G.
|
||||
* \f]
|
||||
*
|
||||
* In the above expressions, the thermodynamic polynomials are expressed
|
||||
* in dimensional units, but the temperature,\f$ t \f$, is divided by 1000. The
|
||||
* following dimensions are assumed in the above expressions:
|
||||
*
|
||||
* - \f$ \tilde{c}_p^0(T)\f$ = Heat Capacity (J/gmol*K)
|
||||
* - \f$ \tilde{h}^0(T) \f$ = standard Enthalpy (kJ/gmol)
|
||||
* - \f$ \tilde{s}^0(T) \f$= standard Entropy (J/gmol*K)
|
||||
* - \f$ t \f$= temperature (K) / 1000.
|
||||
*
|
||||
* For more information about Shomate polynomials, see the NIST website,
|
||||
* http://webbook.nist.gov/
|
||||
*
|
||||
* Before being used within Cantera, the dimensions must be adjusted to those
|
||||
* used by Cantera (i.e., Joules and kmol).
|
||||
*
|
||||
* This function uses two temperature regions, each with a Shomate polynomial
|
||||
* representation to represent the thermo functions. There are 15 coefficients,
|
||||
* therefore, in this representation. The first coefficient is the midrange
|
||||
* temperature.
|
||||
*
|
||||
*
|
||||
* @ingroup spthermo
|
||||
*/
|
||||
class ShomatePoly2 : public SpeciesThermoInterpType {
|
||||
public:
|
||||
|
||||
//! Empty constructor
|
||||
ShomatePoly2()
|
||||
: m_lowT(0.0),
|
||||
m_midT(0.0),
|
||||
m_highT (0.0),
|
||||
m_Pref(0.0),
|
||||
msp_low(0),
|
||||
msp_high(0),
|
||||
m_index(0) {
|
||||
m_coeff.resize(15);
|
||||
}
|
||||
|
||||
//! Constructor used in templated instantiations
|
||||
/*!
|
||||
* @param n Species index
|
||||
* @param tlow Minimum temperature
|
||||
* @param thigh Maximum temperature
|
||||
* @param pref reference pressure (Pa).
|
||||
* @param coeffs Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
* There are 15 coefficients for the 2-zone Shomate polynomial.
|
||||
* The first coefficient is the value of Tmid. The next 7
|
||||
* coefficients are the low temperature range Shomate coefficients.
|
||||
* The last 7 are the high temperature range Shomate coefficients.
|
||||
*/
|
||||
ShomatePoly2(int n, doublereal tlow, doublereal thigh, doublereal pref,
|
||||
const doublereal* coeffs) :
|
||||
m_lowT (tlow),
|
||||
m_midT(0.0),
|
||||
m_highT (thigh),
|
||||
m_Pref (pref),
|
||||
msp_low(0),
|
||||
msp_high(0),
|
||||
m_index (n) {
|
||||
m_coeff.resize(15);
|
||||
std::copy(coeffs, coeffs + 15, m_coeff.begin());
|
||||
m_midT = coeffs[0];
|
||||
msp_low = new ShomatePoly(n, tlow, m_midT, pref, coeffs+1);
|
||||
msp_high = new ShomatePoly(n, m_midT, thigh, pref, coeffs+8);
|
||||
}
|
||||
|
||||
//! Copy constructor
|
||||
/*!
|
||||
* @param b object to be copied.
|
||||
*/
|
||||
ShomatePoly2(const ShomatePoly2& b) :
|
||||
m_lowT (b.m_lowT),
|
||||
m_midT (b.m_midT),
|
||||
m_highT (b.m_highT),
|
||||
m_Pref (b.m_Pref),
|
||||
msp_low(0),
|
||||
msp_high(0),
|
||||
m_coeff (array_fp(15)),
|
||||
m_index (b.m_index) {
|
||||
std::copy(b.m_coeff.begin(),
|
||||
b.m_coeff.begin() + 15,
|
||||
m_coeff.begin());
|
||||
msp_low = new ShomatePoly(m_index, m_lowT, m_midT,
|
||||
m_Pref, &m_coeff[1]);
|
||||
msp_high = new ShomatePoly(m_index, m_midT, m_highT,
|
||||
m_Pref, &m_coeff[8]);
|
||||
}
|
||||
|
||||
//! Assignment operator
|
||||
/*!
|
||||
* @param b object to be copied.
|
||||
*/
|
||||
ShomatePoly2& operator=(const ShomatePoly2& b) {
|
||||
if (&b != this) {
|
||||
m_lowT = b.m_lowT;
|
||||
m_midT = b.m_midT;
|
||||
m_highT = b.m_highT;
|
||||
m_Pref = b.m_Pref;
|
||||
m_index = b.m_index;
|
||||
std::copy(b.m_coeff.begin(),
|
||||
b.m_coeff.begin() + 15,
|
||||
m_coeff.begin());
|
||||
if (msp_low) delete msp_low;
|
||||
if (msp_high) delete msp_high;
|
||||
msp_low = new ShomatePoly(m_index, m_lowT, m_midT,
|
||||
m_Pref, &m_coeff[1]);
|
||||
msp_high = new ShomatePoly(m_index, m_midT, m_highT,
|
||||
m_Pref, &m_coeff[8]);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
virtual ~ShomatePoly2(){
|
||||
delete msp_low;
|
||||
delete msp_high;
|
||||
}
|
||||
|
||||
|
||||
//! duplicator
|
||||
virtual SpeciesThermoInterpType *
|
||||
duplMyselfAsSpeciesThermoInterpType() const {
|
||||
ShomatePoly2* sp = new ShomatePoly2(*this);
|
||||
return (SpeciesThermoInterpType *) sp;
|
||||
}
|
||||
|
||||
//! Returns the minimum temperature that the thermo
|
||||
//! parameterization is valid
|
||||
virtual doublereal minTemp() const { return m_lowT;}
|
||||
|
||||
//! Returns the maximum temperature that the thermo
|
||||
//! parameterization is valid
|
||||
virtual doublereal maxTemp() const { return m_highT;}
|
||||
|
||||
//! Returns the reference pressure (Pa)
|
||||
virtual doublereal refPressure() const { return m_Pref; }
|
||||
|
||||
//! Returns an integer representing the type of parameterization
|
||||
virtual int reportType() const { return SHOMATE2; }
|
||||
|
||||
|
||||
//! Update the properties for this species, given a temperature polynomial
|
||||
/*!
|
||||
* This method is called with a pointer to an array containing the functions of
|
||||
* temperature needed by this parameterization, and three pointers to arrays where the
|
||||
* computed property values should be written. This method updates only one value in
|
||||
* each array.
|
||||
*
|
||||
* Temperature Polynomial:
|
||||
* tt[0] = t;
|
||||
* tt[1] = t*t;
|
||||
* tt[2] = m_t[1]*t;
|
||||
* tt[3] = m_t[2]*t;
|
||||
* tt[4] = 1.0/t;
|
||||
* tt[5] = std::log(t);
|
||||
*
|
||||
* @param tt vector of temperature polynomials
|
||||
* @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).
|
||||
*/
|
||||
virtual void updateProperties(const doublereal* tt,
|
||||
doublereal* cp_R, doublereal* h_RT,
|
||||
doublereal* s_R) const {
|
||||
double T = 1000 * tt[0];
|
||||
if (T <= m_midT) {
|
||||
msp_low->updateProperties(tt, cp_R, h_RT, s_R);
|
||||
} else {
|
||||
msp_high->updateProperties(tt, cp_R, h_RT, s_R);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//! Compute the reference-state property of one species
|
||||
/*!
|
||||
* Given temperature T in K, this method updates the values of
|
||||
* the non-dimensional heat capacity at constant pressure,
|
||||
* enthalpy, and entropy, at the reference pressure, Pref
|
||||
* of one of the species. The species index is used
|
||||
* to reference into the cp_R, h_RT, and s_R arrays.
|
||||
*
|
||||
* @param temp 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).
|
||||
*/
|
||||
virtual void updatePropertiesTemp(const doublereal temp,
|
||||
doublereal* cp_R,
|
||||
doublereal* h_RT,
|
||||
doublereal* s_R) const {
|
||||
if (temp <= m_midT) {
|
||||
msp_low->updatePropertiesTemp(temp, cp_R, h_RT, s_R);
|
||||
} else {
|
||||
msp_high->updatePropertiesTemp(temp, cp_R, h_RT, s_R);
|
||||
}
|
||||
}
|
||||
|
||||
//!This utility function reports back the type of
|
||||
//! parameterization and all of the parameters for the
|
||||
//! species, index.
|
||||
/*!
|
||||
* All parameters are output variables
|
||||
*
|
||||
* @param n Species index
|
||||
* @param type Integer type of the standard type
|
||||
* @param tlow output - Minimum temperature
|
||||
* @param thigh output - Maximum temperature
|
||||
* @param pref output - reference pressure (Pa).
|
||||
* @param coeffs Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
*/
|
||||
virtual void reportParameters(int &n, int &type,
|
||||
doublereal &tlow, doublereal &thigh,
|
||||
doublereal &pref,
|
||||
doublereal* const coeffs) const {
|
||||
n = m_index;
|
||||
type = SHOMATE2;
|
||||
tlow = m_lowT;
|
||||
thigh = m_highT;
|
||||
pref = m_Pref;
|
||||
for (int i = 0; i < 15; i++) {
|
||||
coeffs[i] = m_coeff[i];
|
||||
}
|
||||
}
|
||||
|
||||
//! Modify parameters for the standard state
|
||||
/*!
|
||||
* Here, we take the tact that we will just regenerate the
|
||||
* object.
|
||||
*
|
||||
* @param coeffs Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
*/
|
||||
virtual void modifyParameters(doublereal* coeffs) {
|
||||
delete msp_low;
|
||||
delete msp_high;
|
||||
std::copy(coeffs, coeffs + 15, m_coeff.begin());
|
||||
m_midT = coeffs[0];
|
||||
msp_low = new ShomatePoly(m_index, m_lowT, m_midT, m_Pref, coeffs+1);
|
||||
msp_high = new ShomatePoly(m_index, m_midT, m_highT, m_Pref, coeffs+8);
|
||||
}
|
||||
|
||||
protected:
|
||||
//! Minimum temperature the representation is valid(kelvin)
|
||||
doublereal m_lowT;
|
||||
//! Midrange temperature (kelvin)
|
||||
doublereal m_midT;
|
||||
//! Maximum temperature the representation is valid (kelvin)
|
||||
doublereal m_highT;
|
||||
//! Reference pressure (Pascal)
|
||||
doublereal m_Pref;
|
||||
//! Pointer to the Shomate polynomial for the low temperature region.
|
||||
ShomatePoly *msp_low;
|
||||
//! Pointer to the Shomate polynomial for the high temperature region.
|
||||
ShomatePoly *msp_high;
|
||||
//! Array of the original coefficients.
|
||||
array_fp m_coeff;
|
||||
//! Species index
|
||||
int m_index;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
465
Cantera/src/thermo/ShomateThermo.h
Executable file
465
Cantera/src/thermo/ShomateThermo.h
Executable file
|
|
@ -0,0 +1,465 @@
|
|||
/**
|
||||
* @file ShomateThermo.h
|
||||
* Header for the 2 regions Shomate polynomial
|
||||
* for multiple species in a phase, derived from the
|
||||
* \link Cantera::SpeciesThermo SpeciesThermo\endlink base class (see \ref spthermo and
|
||||
* \link Cantera::ShomateThermo ShomateThermo\endlink).
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
// Copyright 2001 California Institute of Technology
|
||||
|
||||
|
||||
#ifndef CT_SHOMATETHERMO_H
|
||||
#define CT_SHOMATETHERMO_H
|
||||
|
||||
#include "SpeciesThermoMgr.h"
|
||||
#include "ShomatePoly.h"
|
||||
#include "speciesThermoTypes.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
//! A species thermodynamic property manager for the Shomate polynomial parameterization.
|
||||
/*!
|
||||
* This is the parameterization used
|
||||
* in the NIST Chemistry WebBook (http://webbook.nist.gov/chemistry)
|
||||
* The parameterization assumes there are two temperature regions
|
||||
* each with its own Shomate polynomial representation, for each
|
||||
* species in the phase.
|
||||
*
|
||||
* \f[
|
||||
* \tilde{c}_p^0(T) = A + B t + C t^2 + D t^3 + \frac{E}{t^2}
|
||||
* \f]
|
||||
* \f[
|
||||
* \tilde{h}^0(T) = A t + \frac{B t^2}{2} + \frac{C t^3}{3}
|
||||
+ \frac{D t^4}{4} - \frac{E}{t} + F.
|
||||
* \f]
|
||||
* \f[
|
||||
* \tilde{s}^0(T) = A\ln t + B t + \frac{C t^2}{2}
|
||||
+ \frac{D t^3}{3} - \frac{E}{2t^2} + G.
|
||||
* \f]
|
||||
*
|
||||
* In the above expressions, the thermodynamic polynomials are expressed
|
||||
* in dimensional units, but the temperature,\f$ t \f$, is divided by 1000. The
|
||||
* following dimensions are assumed in the above expressions:
|
||||
*
|
||||
* - \f$ \tilde{c}_p^0(T)\f$ = Heat Capacity (J/gmol*K)
|
||||
* - \f$ \tilde{h}^0(T) \f$ = standard Enthalpy (kJ/gmol)
|
||||
* - \f$ \tilde{s}^0(T) \f$= standard Entropy (J/gmol*K)
|
||||
* - \f$ t \f$= temperature (K) / 1000.
|
||||
*
|
||||
* Note, the polynomial data (i.e., A, ... , G) is entered in dimensional
|
||||
* form.
|
||||
*
|
||||
* This is in contrast to the NASA database polynomials which are entered in
|
||||
* nondimensional form (i.e., NASA parameterizes C_p/R, while Shomate
|
||||
* parameterizes C_p assuming units of J/gmol*K - and kJ/gmol*K for H).
|
||||
* Note, also that the H - H_298.15 equation has units of kJ/gmol, because of
|
||||
* the implicit integration of (t = T 1000), which provides a
|
||||
* multiplier of 1000 to the Enthalpy equation.
|
||||
*
|
||||
* @ingroup spthermo
|
||||
*/
|
||||
class ShomateThermo : public SpeciesThermo {
|
||||
|
||||
public:
|
||||
|
||||
//! Initialized to the type of parameterization
|
||||
/*!
|
||||
* Note, this value is used in some template functions
|
||||
*/
|
||||
const int ID;
|
||||
|
||||
//! constructor
|
||||
ShomateThermo() :
|
||||
ID(SHOMATE),
|
||||
m_tlow_max(0.0),
|
||||
m_thigh_min(1.e30),
|
||||
m_p0(-1.0),
|
||||
m_ngroups(0)
|
||||
{ m_t.resize(7); }
|
||||
|
||||
//! destructor
|
||||
virtual ~ShomateThermo() {}
|
||||
|
||||
//! Install a new species thermodynamic property
|
||||
//! parameterization for one species using Shomate polynomials
|
||||
//!
|
||||
/*!
|
||||
* Two temperature regions are assumed.
|
||||
*
|
||||
* @param name Name of the species
|
||||
* @param index Species index
|
||||
* @param type int flag specifying the type of parameterization to be
|
||||
* installed.
|
||||
* @param c Vector of coefficients for the parameterization.
|
||||
* There are 15 coefficients for the 2-zone Shomate polynomial.
|
||||
* The first coefficient is the value of Tmid. The next 7
|
||||
* coefficients are the low temperature range Shomate coefficients.
|
||||
* The last 7 are the high temperature range Shomate coefficients.
|
||||
*
|
||||
* @param minTemp minimum temperature for which this parameterization
|
||||
* is valid.
|
||||
* @param maxTemp maximum temperature for which this parameterization
|
||||
* is valid.
|
||||
* @param refPressure standard-state pressure for this
|
||||
* parameterization.
|
||||
*
|
||||
* @see ShomatePoly
|
||||
* @see ShomatePoly2
|
||||
*/
|
||||
virtual void install(string name, int index, int type,
|
||||
const doublereal* c,
|
||||
doublereal minTemp, doublereal maxTemp,
|
||||
doublereal refPressure) {
|
||||
int imid = int(c[0]); // midpoint temp converted to integer
|
||||
int igrp = m_index[imid]; // has this value been seen before?
|
||||
if (igrp == 0) { // if not, prepare new group
|
||||
vector<ShomatePoly> v;
|
||||
m_high.push_back(v);
|
||||
m_low.push_back(v);
|
||||
m_tmid.push_back(c[0]);
|
||||
m_index[imid] = igrp = static_cast<int>(m_high.size());
|
||||
m_ngroups++;
|
||||
}
|
||||
m_group_map[index] = igrp;
|
||||
m_posInGroup_map[index] = (int) m_low[igrp-1].size();
|
||||
doublereal tlow = minTemp;
|
||||
doublereal tmid = c[0];
|
||||
doublereal thigh = maxTemp;
|
||||
|
||||
const doublereal* clow = c + 1;
|
||||
const doublereal* chigh = c + 8;
|
||||
m_high[igrp-1].push_back(ShomatePoly(index, tmid, thigh,
|
||||
refPressure, chigh));
|
||||
m_low[igrp-1].push_back(ShomatePoly(index, tlow, tmid,
|
||||
refPressure, clow));
|
||||
if (tlow > m_tlow_max) m_tlow_max = tlow;
|
||||
if (thigh < m_thigh_min) m_thigh_min = thigh;
|
||||
|
||||
if ((int) m_tlow.size() < index + 1) {
|
||||
m_tlow.resize(index + 1, tlow);
|
||||
m_thigh.resize(index + 1, thigh);
|
||||
}
|
||||
m_tlow[index] = tlow;
|
||||
m_thigh[index] = thigh;
|
||||
|
||||
if (m_p0 < 0.0) {
|
||||
m_p0 = refPressure;
|
||||
} else if (fabs(m_p0 - refPressure) > 0.1) {
|
||||
string logmsg = " WARNING ShomateThermo: New Species, " + name
|
||||
+ ", has a different reference pressure, "
|
||||
+ fp2str(refPressure) + ", than existing reference pressure, " + fp2str(m_p0) + "\n";
|
||||
writelog(logmsg);
|
||||
logmsg = " This may become a fatal error in the future \n";
|
||||
writelog(logmsg);
|
||||
}
|
||||
m_p0 = refPressure;
|
||||
|
||||
}
|
||||
|
||||
//! 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).
|
||||
*/
|
||||
virtual void update_one(int k, doublereal t, doublereal* cp_R,
|
||||
doublereal* h_RT, doublereal* s_R) const {
|
||||
|
||||
doublereal tt = 1.e-3*t;
|
||||
m_t[0] = tt;
|
||||
m_t[1] = tt*tt;
|
||||
m_t[2] = m_t[1]*tt;
|
||||
m_t[3] = 1.0/m_t[1];
|
||||
m_t[4] = log(tt);
|
||||
m_t[5] = 1.0/GasConstant;
|
||||
m_t[6] = 1.0/(GasConstant * t);
|
||||
|
||||
int grp = m_group_map[k];
|
||||
int pos = m_posInGroup_map[k];
|
||||
const vector<ShomatePoly> &mlg = m_low[grp-1];
|
||||
const ShomatePoly *nlow = &(mlg[pos]);
|
||||
|
||||
doublereal tmid = nlow->maxTemp();
|
||||
if (t < tmid) {
|
||||
nlow->updateProperties(&m_t[0], cp_R, h_RT, s_R);
|
||||
} else {
|
||||
const vector<ShomatePoly> &mhg = m_high[grp-1];
|
||||
const ShomatePoly *nhigh = &(mhg[pos]);
|
||||
nhigh->updateProperties(&m_t[0], cp_R, h_RT, s_R);
|
||||
}
|
||||
}
|
||||
|
||||
//! Compute the reference-state properties for all species.
|
||||
/*!
|
||||
* Given temperature T in K, this method updates the values of
|
||||
* the non-dimensional heat capacity at constant pressure,
|
||||
* enthalpy, and entropy, at the reference pressure, Pref
|
||||
* of each of the standard states.
|
||||
*
|
||||
* @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).
|
||||
*/
|
||||
virtual void update(doublereal t, doublereal* cp_R,
|
||||
doublereal* h_RT, doublereal* s_R) const {
|
||||
int i;
|
||||
|
||||
doublereal tt = 1.e-3*t;
|
||||
m_t[0] = tt;
|
||||
m_t[1] = tt*tt;
|
||||
m_t[2] = m_t[1]*tt;
|
||||
m_t[3] = 1.0/m_t[1];
|
||||
m_t[4] = log(tt);
|
||||
m_t[5] = 1.0/GasConstant;
|
||||
m_t[6] = 1.0/(GasConstant * t);
|
||||
|
||||
vector<ShomatePoly>::const_iterator _begin, _end;
|
||||
for (i = 0; i != m_ngroups; i++) {
|
||||
if (t > m_tmid[i]) {
|
||||
_begin = m_high[i].begin();
|
||||
_end = m_high[i].end();
|
||||
}
|
||||
else {
|
||||
_begin = m_low[i].begin();
|
||||
_end = m_low[i].end();
|
||||
}
|
||||
for (; _begin != _end; ++_begin) {
|
||||
_begin->updateProperties(&m_t[0], cp_R, h_RT, s_R);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Minimum temperature.
|
||||
/*!
|
||||
* If no argument is supplied, this
|
||||
* method returns the minimum temperature for which \e all
|
||||
* parameterizations are valid. If an integer index k is
|
||||
* supplied, then the value returned is the minimum
|
||||
* temperature for species k in the phase.
|
||||
*
|
||||
* @param k Species index
|
||||
*/
|
||||
virtual doublereal minTemp(int k=-1) const {
|
||||
if (k < 0)
|
||||
return m_tlow_max;
|
||||
else
|
||||
return m_tlow[k];
|
||||
}
|
||||
|
||||
//! Maximum temperature.
|
||||
/*!
|
||||
* If no argument is supplied, this
|
||||
* method returns the maximum temperature for which \e all
|
||||
* parameterizations are valid. If an integer index k is
|
||||
* supplied, then the value returned is the maximum
|
||||
* temperature for parameterization k.
|
||||
*
|
||||
* @param k species index
|
||||
*/
|
||||
virtual doublereal maxTemp(int k=-1) const {
|
||||
if (k < 0)
|
||||
return m_thigh_min;
|
||||
else
|
||||
return m_thigh[k];
|
||||
}
|
||||
|
||||
//! The reference-state pressure for species k.
|
||||
/*!
|
||||
*
|
||||
* returns the reference state pressure in Pascals for
|
||||
* species k. If k is left out of the argument list,
|
||||
* it returns the reference state pressure for the first
|
||||
* species.
|
||||
* Note that some SpeciesThermo implementations, such
|
||||
* as those for ideal gases, require that all species
|
||||
* in the same phase have the same reference state pressures.
|
||||
*
|
||||
* @param k species index
|
||||
*/
|
||||
virtual doublereal refPressure(int k=-1) const {
|
||||
return m_p0;
|
||||
}
|
||||
|
||||
//! This utility function reports the type of parameterization
|
||||
//! used for the species with index number index.
|
||||
/*!
|
||||
*
|
||||
* @param index Species index
|
||||
*/
|
||||
virtual int reportType(int index) const { return SHOMATE; }
|
||||
|
||||
/*!
|
||||
* This utility function reports back the type of
|
||||
* parameterization and all of the parameters for the
|
||||
* species, index.
|
||||
*
|
||||
* @param index Species index
|
||||
* @param type Integer type of the standard type
|
||||
* @param c Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
*
|
||||
* @param minTemp output - Minimum temperature
|
||||
* @param maxTemp output - Maximum temperature
|
||||
* @param refPressure output - reference pressure (Pa).
|
||||
*/
|
||||
virtual void reportParams(int index, int &type,
|
||||
doublereal * const c,
|
||||
doublereal &minTemp,
|
||||
doublereal &maxTemp,
|
||||
doublereal &refPressure) const {
|
||||
type = reportType(index);
|
||||
if (type == SHOMATE) {
|
||||
int grp = m_group_map[index];
|
||||
int pos = m_posInGroup_map[index];
|
||||
int itype = SHOMATE;
|
||||
const vector<ShomatePoly> &mlg = m_low[grp-1];
|
||||
const vector<ShomatePoly> &mhg = m_high[grp-1];
|
||||
const ShomatePoly *lowPoly = &(mlg[pos]);
|
||||
const ShomatePoly *highPoly = &(mhg[pos]);
|
||||
doublereal tmid = lowPoly->maxTemp();
|
||||
c[0] = tmid;
|
||||
int n;
|
||||
double ttemp;
|
||||
lowPoly->reportParameters(n, itype, minTemp, ttemp, refPressure,
|
||||
c + 1);
|
||||
if (n != index) {
|
||||
throw CanteraError(" ", "confused");
|
||||
}
|
||||
if (itype != SHOMATE && itype != SHOMATE1) {
|
||||
throw CanteraError(" ", "confused");
|
||||
}
|
||||
highPoly->reportParameters(n, itype, ttemp, maxTemp,
|
||||
refPressure, c + 8);
|
||||
if (n != index) {
|
||||
throw CanteraError(" ", "confused");
|
||||
}
|
||||
if (itype != SHOMATE && itype != SHOMATE1) {
|
||||
throw CanteraError(" ", "confused");
|
||||
}
|
||||
} else {
|
||||
throw CanteraError(" ", "confused");
|
||||
}
|
||||
}
|
||||
|
||||
//! Modify parameters for the standard state
|
||||
/*!
|
||||
* @param index Species index
|
||||
* @param c Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
*/
|
||||
virtual void modifyParams(int index, doublereal *c) {
|
||||
int type = reportType(index);
|
||||
if (type == SHOMATE) {
|
||||
int grp = m_group_map[index];
|
||||
int pos = m_posInGroup_map[index];
|
||||
vector<ShomatePoly> &mlg = m_low[grp-1];
|
||||
vector<ShomatePoly> &mhg = m_high[grp-1];
|
||||
ShomatePoly *lowPoly = &(mlg[pos]);
|
||||
ShomatePoly *highPoly = &(mhg[pos]);
|
||||
doublereal tmid = lowPoly->maxTemp();
|
||||
if (fabs(c[0] - tmid) > 0.001) {
|
||||
throw CanteraError("modifyParams", "can't change mid temp");
|
||||
}
|
||||
|
||||
lowPoly->modifyParameters(c + 1);
|
||||
|
||||
highPoly->modifyParameters(c + 8);
|
||||
|
||||
} else {
|
||||
throw CanteraError(" ", "confused");
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
//! Vector of vector of NasaPoly1's for the high temp region.
|
||||
/*!
|
||||
* This is the high temp region representation.
|
||||
* The first Length is equal to the number of groups.
|
||||
* The second vector is equal to the number of species
|
||||
* in that particular group.
|
||||
*/
|
||||
vector<vector<ShomatePoly> > m_high;
|
||||
|
||||
//! Vector of vector of NasaPoly1's for the low temp region.
|
||||
/*!
|
||||
* This is the low temp region representation.
|
||||
* The first Length is equal to the number of groups.
|
||||
* The second vector is equal to the number of species
|
||||
* in that particular group.
|
||||
*/
|
||||
vector<vector<ShomatePoly> > m_low;
|
||||
|
||||
//! Map between the midpoint temperature, as an int, to the group number
|
||||
/*!
|
||||
* Length is equal to the number of groups. Only used in the setup.
|
||||
*/
|
||||
map<int, int> m_index;
|
||||
|
||||
//! Vector of log temperature limits
|
||||
/*!
|
||||
* Length is equal to the number of groups.
|
||||
*/
|
||||
vector_fp m_tmid;
|
||||
|
||||
//! Maximum value of the low temperature limit
|
||||
doublereal m_tlow_max;
|
||||
|
||||
//! Minimum value of the high temperature limit
|
||||
doublereal m_thigh_min;
|
||||
|
||||
//! Vector of low temperature limits (species index)
|
||||
/*!
|
||||
* Length is equal to number of species
|
||||
*/
|
||||
vector_fp m_tlow;
|
||||
|
||||
//! Vector of low temperature limits (species index)
|
||||
/*!
|
||||
* Length is equal to number of species
|
||||
*/
|
||||
vector_fp m_thigh;
|
||||
|
||||
//! Reference pressure (Pa)
|
||||
/*!
|
||||
* all species must have the same reference pressure.
|
||||
*/
|
||||
doublereal m_p0;
|
||||
|
||||
//! number of groups
|
||||
int m_ngroups;
|
||||
|
||||
//! Vector of temperature polynomials
|
||||
mutable vector_fp m_t;
|
||||
|
||||
/*!
|
||||
* This map takes as its index, the species index in the phase.
|
||||
* It returns the group index, where the temperature polynomials
|
||||
* for that species are stored. group indecises start at 1,
|
||||
* so a decrement is always performed to access vectors.
|
||||
*/
|
||||
mutable map<int, int> m_group_map;
|
||||
|
||||
/*!
|
||||
* This map takes as its index, the species index in the phase.
|
||||
* It returns the position index within the group, where the
|
||||
* temperature polynomials for that species are storred.
|
||||
*/
|
||||
mutable map<int, int> m_posInGroup_map;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
379
Cantera/src/thermo/SimpleThermo.h
Normal file
379
Cantera/src/thermo/SimpleThermo.h
Normal file
|
|
@ -0,0 +1,379 @@
|
|||
/**
|
||||
* @file SimpleThermo.h
|
||||
* Header for the SimpleThermo (constant heat capacity) species reference-state model
|
||||
* for multiple species in a phase, derived from the
|
||||
* \link Cantera::SpeciesThermo SpeciesThermo\endlink base class (see \ref spthermo and
|
||||
* \link Cantera::SimpleThermo SimpleThermo\endlink).
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef CT_SIMPLETHERMO_H
|
||||
#define CT_SIMPLETHERMO_H
|
||||
|
||||
#include "SpeciesThermoMgr.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
/*!
|
||||
* A constant-heat capacity species thermodynamic property manager class.
|
||||
* This makes the
|
||||
* assumption that the heat capacity is a constant. Then, the following
|
||||
* relations are used to complete the specification of the thermodynamic
|
||||
* functions for each species in the phase.
|
||||
*
|
||||
* \f[
|
||||
* \frac{c_p(T)}{R} = Cp0\_R
|
||||
* \f]
|
||||
* \f[
|
||||
* \frac{h^0(T)}{RT} = \frac{1}{T} * (h0\_R + (T - T_0) * Cp0\_R)
|
||||
* \f]
|
||||
* \f[
|
||||
* \frac{s^0(T)}{R} = (s0\_R + (log(T) - log(T_0)) * Cp0\_R)
|
||||
* \f]
|
||||
*
|
||||
* This parameterization takes 4 input values. These are:
|
||||
* - c[0] = \f$ T_0 \f$(Kelvin)
|
||||
* - c[1] = \f$ H_k^o(T_0, p_{ref}) \f$ (J/kmol)
|
||||
* - c[2] = \f$ S_k^o(T_0, p_{ref}) \f$ (J/kmol K)
|
||||
* - c[3] = \f$ {Cp}_k^o(T_0, p_{ref}) \f$ (J(kmol K)
|
||||
*
|
||||
* All species must have the same reference pressure.
|
||||
* The single-species standard-state property Manager ConstCpPoly has the same
|
||||
* parameterization as the SimpleThermo class does.
|
||||
*
|
||||
* @see ConstCpPoly
|
||||
*
|
||||
* @ingroup spthermo
|
||||
*/
|
||||
class SimpleThermo : public SpeciesThermo {
|
||||
|
||||
public:
|
||||
|
||||
//! Initialized to the type of parameterization
|
||||
/*!
|
||||
* Note, this value is used in some template functions. For this object the
|
||||
* value is SIMPLE.
|
||||
*/
|
||||
const int ID;
|
||||
|
||||
//! Constructor
|
||||
SimpleThermo() :
|
||||
ID(SIMPLE),
|
||||
m_tlow_max(0.0),
|
||||
m_thigh_min(1.e30),
|
||||
m_p0(-1.0),
|
||||
m_nspData(0) {}
|
||||
|
||||
//! Destructor
|
||||
virtual ~SimpleThermo() {}
|
||||
|
||||
//! Install a new species thermodynamic property
|
||||
//! parameterization for one species.
|
||||
/*!
|
||||
*
|
||||
* @param name String name of the species
|
||||
* @param index Species index, k
|
||||
* @param type int flag specifying the type of parameterization to be
|
||||
* installed.
|
||||
* @param c Vector of coefficients for the parameterization.
|
||||
* There are 4 coefficients. The values (and units) are the following
|
||||
* - c[0] = \f$ T_0 \f$(Kelvin)
|
||||
* - c[1] = \f$ H_k^o(T_0, p_{ref}) \f$ (J/kmol)
|
||||
* - c[2] = \f$ S_k^o(T_0, p_{ref}) \f$ (J/kmol K)
|
||||
* - c[3] = \f$ {Cp}_k^o(T_0, p_{ref}) \f$ (J(kmol K)
|
||||
*
|
||||
* @param minTemp minimum temperature for which this parameterization
|
||||
* is valid.
|
||||
* @param maxTemp maximum temperature for which this parameterization
|
||||
* is valid.
|
||||
* @param refPressure standard-state pressure for this
|
||||
* parameterization.
|
||||
*
|
||||
* @see ConstCpPoly
|
||||
*/
|
||||
virtual void install(string name, int index, int type,
|
||||
const doublereal* c,
|
||||
doublereal minTemp, doublereal maxTemp, doublereal refPressure) {
|
||||
//writelog("installing const_cp for species "+name+"\n");
|
||||
m_logt0.push_back(log(c[0]));
|
||||
m_t0.push_back(c[0]);
|
||||
m_h0_R.push_back(c[1]/GasConstant);
|
||||
m_s0_R.push_back(c[2]/GasConstant);
|
||||
m_cp0_R.push_back(c[3]/GasConstant);
|
||||
m_index.push_back(index);
|
||||
m_loc[index] = m_nspData;
|
||||
m_nspData++;
|
||||
doublereal tlow = minTemp;
|
||||
doublereal thigh = maxTemp;
|
||||
|
||||
if (tlow > m_tlow_max) m_tlow_max = tlow;
|
||||
if (thigh < m_thigh_min) m_thigh_min = thigh;
|
||||
|
||||
if ((int) m_tlow.size() < index + 1) {
|
||||
m_tlow.resize(index + 1, tlow);
|
||||
m_thigh.resize(index + 1, thigh);
|
||||
}
|
||||
m_tlow[index] = tlow;
|
||||
m_thigh[index] = thigh;
|
||||
|
||||
if (m_p0 < 0.0) {
|
||||
m_p0 = refPressure;
|
||||
} else if (fabs(m_p0 - refPressure) > 0.1) {
|
||||
string logmsg = " WARNING SimpleThermo: New Species, " + name +
|
||||
", has a different reference pressure, "
|
||||
+ fp2str(refPressure) + ", than existing reference pressure, " + fp2str(m_p0) + "\n";
|
||||
writelog(logmsg);
|
||||
logmsg = " This may become a fatal error in the future \n";
|
||||
writelog(logmsg);
|
||||
}
|
||||
m_p0 = refPressure;
|
||||
}
|
||||
|
||||
//! Compute the reference-state properties for all species.
|
||||
/*!
|
||||
* Given temperature T in K, this method updates the values of
|
||||
* the non-dimensional heat capacity at constant pressure,
|
||||
* enthalpy, and entropy, at the reference pressure, Pref
|
||||
* of each of the standard states.
|
||||
*
|
||||
* @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).
|
||||
*/
|
||||
virtual void update(doublereal t, doublereal* cp_R,
|
||||
doublereal* h_RT, doublereal* s_R) const {
|
||||
int k, ki;
|
||||
doublereal logt = log(t);
|
||||
doublereal rt = 1.0/t;
|
||||
for (k = 0; k < m_nspData; k++) {
|
||||
ki = m_index[k];
|
||||
cp_R[ki] = m_cp0_R[k];
|
||||
h_RT[ki] = rt*(m_h0_R[k] + (t - m_t0[k]) * m_cp0_R[k]);
|
||||
s_R[ki] = m_s0_R[k] + m_cp0_R[k] * (logt - m_logt0[k]);
|
||||
}
|
||||
}
|
||||
|
||||
//! 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).
|
||||
*/
|
||||
virtual void update_one(int k, doublereal t, doublereal* cp_R,
|
||||
doublereal* h_RT, doublereal* s_R) const {
|
||||
doublereal logt = log(t);
|
||||
doublereal rt = 1.0/t;
|
||||
int loc = m_loc[k];
|
||||
cp_R[k] = m_cp0_R[loc];
|
||||
h_RT[k] = rt*(m_h0_R[loc] + (t - m_t0[loc]) * m_cp0_R[loc]);
|
||||
s_R[k] = m_s0_R[loc] + m_cp0_R[loc] * (logt - m_logt0[loc]);
|
||||
}
|
||||
|
||||
//! Minimum temperature.
|
||||
/*!
|
||||
* If no argument is supplied, this
|
||||
* method returns the minimum temperature for which \e all
|
||||
* parameterizations are valid. If an integer index k is
|
||||
* supplied, then the value returned is the minimum
|
||||
* temperature for species k in the phase.
|
||||
*
|
||||
* @param k Species index
|
||||
*/
|
||||
virtual doublereal minTemp(int k=-1) const {
|
||||
if (k < 0)
|
||||
return m_tlow_max;
|
||||
else
|
||||
return m_tlow[m_loc[k]];
|
||||
}
|
||||
|
||||
//! Maximum temperature.
|
||||
/*!
|
||||
* If no argument is supplied, this
|
||||
* method returns the maximum temperature for which \e all
|
||||
* parameterizations are valid. If an integer index k is
|
||||
* supplied, then the value returned is the maximum
|
||||
* temperature for parameterization k.
|
||||
*
|
||||
* @param k Species Index
|
||||
*/
|
||||
virtual doublereal maxTemp(int k=-1) const {
|
||||
if (k < 0)
|
||||
return m_thigh_min;
|
||||
else
|
||||
return m_thigh[m_loc[k]];
|
||||
}
|
||||
|
||||
//! The reference-state pressure for species k.
|
||||
/*!
|
||||
*
|
||||
* returns the reference state pressure in Pascals for
|
||||
* species k. If k is left out of the argument list,
|
||||
* it returns the reference state pressure for the first
|
||||
* species.
|
||||
* Note that some SpeciesThermo implementations, such
|
||||
* as those for ideal gases, require that all species
|
||||
* in the same phase have the same reference state pressures.
|
||||
*
|
||||
* @param k Species Index
|
||||
*/
|
||||
virtual doublereal refPressure(int k=-1) const {return m_p0;}
|
||||
|
||||
//! This utility function reports the type of parameterization
|
||||
//! used for the species with index number index.
|
||||
/*!
|
||||
*
|
||||
* @param index Species index
|
||||
*/
|
||||
virtual int reportType(int index) const { return SIMPLE; }
|
||||
|
||||
/*!
|
||||
* This utility function reports back the type of
|
||||
* parameterization and all of the parameters for the
|
||||
* species, index.
|
||||
*
|
||||
* @param index Species index
|
||||
* @param type Integer type of the standard type
|
||||
* @param c Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
* For the SimpleThermo object, there are 4 coefficients.
|
||||
* @param minTemp output - Minimum temperature
|
||||
* @param maxTemp output - Maximum temperature
|
||||
* @param refPressure output - reference pressure (Pa).
|
||||
*
|
||||
*/
|
||||
virtual void reportParams(int index, int &type,
|
||||
doublereal * const c,
|
||||
doublereal &minTemp,
|
||||
doublereal &maxTemp,
|
||||
doublereal &refPressure) const {
|
||||
type = reportType(index);
|
||||
int loc = m_loc[index];
|
||||
if (type == SIMPLE) {
|
||||
c[0] = m_t0[loc];
|
||||
c[1] = m_h0_R[loc] * GasConstant;
|
||||
c[2] = m_s0_R[loc] * GasConstant;
|
||||
c[3] = m_cp0_R[loc] * GasConstant;
|
||||
minTemp = m_tlow[loc];
|
||||
maxTemp = m_thigh[loc];
|
||||
refPressure = m_p0;
|
||||
}
|
||||
}
|
||||
|
||||
//! Modify parameters for the standard state
|
||||
/*!
|
||||
* The thermo parameterization for a single species is overwritten.
|
||||
*
|
||||
* @param index Species index
|
||||
* @param c Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
* Must be length >= 4.
|
||||
*/
|
||||
virtual void modifyParams(int index, doublereal *c) {
|
||||
int loc = m_loc[index];
|
||||
if (loc < 0) {
|
||||
throw CanteraError("SimpleThermo::modifyParams",
|
||||
"modifying parameters for species which hasn't been set yet");
|
||||
}
|
||||
/*
|
||||
* Change the data
|
||||
*/
|
||||
m_t0[loc] = c[0];
|
||||
m_h0_R[loc] = c[1] / GasConstant;
|
||||
m_s0_R[loc] = c[2] / GasConstant;
|
||||
m_cp0_R[loc] = c[3] / GasConstant;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
//! Mapping between the species index and the vector index where the coefficients are kept
|
||||
/*!
|
||||
* This object doesn't have a one-to one correspondence between the species index, kspec,
|
||||
* and the data location index,indexData, m_cp0_R[indexData].
|
||||
* This index keeps track of it.
|
||||
* indexData = m_loc[kspec]
|
||||
*/
|
||||
mutable map<int, int> m_loc;
|
||||
|
||||
//! Map between the vector index where the coefficients are kept and the species index
|
||||
/*!
|
||||
* Length is equal to the number of dataPoints.
|
||||
* kspec = m_index[indexData]
|
||||
*/
|
||||
vector_int m_index;
|
||||
|
||||
//! Maximum value of the low temperature limit
|
||||
doublereal m_tlow_max;
|
||||
|
||||
//! Minimum value of the high temperature limit
|
||||
doublereal m_thigh_min;
|
||||
|
||||
//! Vector of low temperature limits (species index)
|
||||
/*!
|
||||
* Length is equal to number of data points
|
||||
*/
|
||||
vector_fp m_tlow;
|
||||
|
||||
//! Vector of low temperature limits (species index)
|
||||
/*!
|
||||
* Length is equal to number of data points
|
||||
*/
|
||||
vector_fp m_thigh;
|
||||
|
||||
//! Vector of base temperatures (kelvin)
|
||||
/*!
|
||||
* Length is equal to the number of species data points
|
||||
*/
|
||||
vector_fp m_t0;
|
||||
|
||||
//! Vector of base log temperatures (kelvin)
|
||||
/*!
|
||||
* Length is equal to the number of species data points
|
||||
*/
|
||||
vector_fp m_logt0;
|
||||
|
||||
//! Vector of base dimensionless Enthalpies
|
||||
/*!
|
||||
* Length is equal to the number of species data points
|
||||
*/
|
||||
vector_fp m_h0_R;
|
||||
|
||||
//! Vector of base dimensionless Entropies
|
||||
/*!
|
||||
* Length is equal to the number of species data points
|
||||
*/
|
||||
vector_fp m_s0_R;
|
||||
|
||||
//! Vector of base dimensionless heat capacities
|
||||
/*!
|
||||
* Length is equal to the number of species data points
|
||||
*/
|
||||
vector_fp m_cp0_R;
|
||||
|
||||
//! Reference pressure (Pa)
|
||||
/*!
|
||||
* all species must have the same reference pressure.
|
||||
*/
|
||||
doublereal m_p0;
|
||||
|
||||
//! Number of species data points in the object.
|
||||
/*!
|
||||
* This is less than or equal to the number of species in the phase.
|
||||
*/
|
||||
int m_nspData;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
298
Cantera/src/thermo/SpeciesThermo.h
Executable file
298
Cantera/src/thermo/SpeciesThermo.h
Executable file
|
|
@ -0,0 +1,298 @@
|
|||
/**
|
||||
* @file SpeciesThermo.h
|
||||
* Virtual base class for the calculation of multiple-species thermodynamic
|
||||
* property managers and text for the spthermo module (see \ref spthermo
|
||||
* and class \link Cantera::SpeciesThermo SpeciesThermo\endlink).
|
||||
*
|
||||
* We also describe the doxygen module spthermo (see \ref spthermo )
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
// Copyright 2001 California Institute of Technology
|
||||
|
||||
|
||||
#ifndef CT_SPECIESTHERMO_H
|
||||
#define CT_SPECIESTHERMO_H
|
||||
|
||||
#include "ct_defs.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
/**
|
||||
* @defgroup spthermo Species Standard-State Thermodynamic Properties
|
||||
*
|
||||
* To compute the thermodynamic properties of multicomponent
|
||||
* solutions, it is necessary to know something about the
|
||||
* thermodynamic properties of the individual species present in
|
||||
* the solution. Exactly what sort of species properties are
|
||||
* required depends on the thermodynamic model for the
|
||||
* solution. For a gaseous solution (i.e., a gas mixture), the
|
||||
* species properties required are usually ideal gas properties at
|
||||
* the mixture temperature and at a reference pressure (often 1
|
||||
* atm or 1 bar). For other types of solutions, however, it may
|
||||
* not be possible to isolate the species in a "pure" state. For
|
||||
* example, the thermodynamic properties of, say, Na+ and Cl- in
|
||||
* saltwater are not easily determined from data on the properties
|
||||
* of solid NaCl, or solid Na metal, or chlorine gas. In this
|
||||
* case, the solvation in water is fundamental to the identity of
|
||||
* the species, and some other reference state must be used. One
|
||||
* common convention for liquid solutions is to use thermodynamic
|
||||
* data for the solutes for the limit of infinite dilution in the
|
||||
* pure solvent; another convention is to reference all properties
|
||||
* to unit molality.
|
||||
*
|
||||
* In defining these standard states for species in a phase, we make
|
||||
* the following definition. A reference state is a standard state
|
||||
* of a species in a phase limited to one pressure, the reference
|
||||
* pressure. The reference state specifies the dependence of all
|
||||
* thermodynamic functions as a function of the temperature, in
|
||||
* between a minimum temperature and a maximum temperature. The
|
||||
* reference state also specifies the molar volume of the species
|
||||
* as a function of temperature. The molar volume is a thermodynamic
|
||||
* function.
|
||||
* A full standard state does the same thing as a reference state,
|
||||
* but specifies the thermodynamics functions at all pressures.
|
||||
*
|
||||
* Whatever the conventions used by a particular solution model,
|
||||
* means need to be provided to compute the species properties in
|
||||
* the reference state. Class SpeciesThermo is the base class
|
||||
* for a family of classes that compute properties of all
|
||||
* species in a phase in their reference states, for a range of temperatures.
|
||||
* Note, the pressure dependence of the species thermodynamic functions is not
|
||||
* handled by this particular species thermodynamic model. %SpeciesThermo
|
||||
* calculates the thermodynamic values of all species in a single
|
||||
* phase during each call.
|
||||
*
|
||||
*
|
||||
* The following classes inherit from %SpeciesThermo. Each of these classes
|
||||
* handle multiple species, usually all of the species in a phase.
|
||||
*
|
||||
* - NasaThermo in file NasaThermo.h
|
||||
* - This is a two zone model, with each zone consisting of a 7
|
||||
* coefficient Nasa Polynomial format.
|
||||
* .
|
||||
* - ShomateThermo in file ShomateThermo.h
|
||||
* - This is a two zone model, with each zone consisting of a 7
|
||||
* coefficient Shomate Polynomial format.
|
||||
* .
|
||||
* - SimpleThermo in file SimpleThermo.h
|
||||
* - This is a one-zone constant heat capacity model.
|
||||
* .
|
||||
* - GeneralSpeciesThermo in file GeneralSpeciesThermo.h
|
||||
* - This is a general model. Each species is handled separately
|
||||
* via a vector over SpeciesThermoInterpType classes.
|
||||
* .
|
||||
* - SpeciesThermo1 in file SpeciesThermoMgr.h
|
||||
* - SpeciesThermoDuo in file SpeciesThermoMgr.h
|
||||
* - This is a combination of two SpeciesThermo types.
|
||||
* .
|
||||
* .
|
||||
*
|
||||
* The class SpeciesThermoInterpType is a pure virtual base class for
|
||||
* calculation of thermodynamic functions for a single species
|
||||
* in its reference state.
|
||||
* The following classes inherit from %SpeciesThermoInterpType
|
||||
* - NasaPoly1 in file NasaPoly1.h
|
||||
* - This is a one zone model, consisting of a 7
|
||||
* coefficient Nasa Polynomial format.
|
||||
* .
|
||||
* - NasaPoly2 in file NasaPoly2.h
|
||||
* - This is a two zone model, with each zone consisting of a 7
|
||||
* coefficient Nasa Polynomial format.
|
||||
* .
|
||||
* - ShomatePoly in file ShomatePoly.h
|
||||
* - This is a one zone model, consisting of a 7
|
||||
* coefficient Shomate Polynomial format.
|
||||
* .
|
||||
* - ShomatePoly2 in file ShomatePoly.h
|
||||
* - This is a two zone model, with each zone consisting of a 7
|
||||
* coefficient Shomate Polynomial format.
|
||||
* .
|
||||
* - ConstCpPoly in file ConstCpPoly.h
|
||||
* - This is a one-zone constant heat capacity model.
|
||||
* .
|
||||
* - Mu0Poly in file Mu0Poly.h
|
||||
* - This is a multizoned model. The chemical potential is given
|
||||
* at a set number of temperatures. Between each temperature
|
||||
* the heat capacity is treated as a constant.
|
||||
* .
|
||||
* .
|
||||
*/
|
||||
//@{
|
||||
|
||||
//////////////////////// class SpeciesThermo ////////////////////
|
||||
|
||||
|
||||
//! Pure Virtual base class for the species thermo manager classes.
|
||||
/*!
|
||||
* This class defines the interface which all subclasses must implement.
|
||||
*
|
||||
* Class %SpeciesThermo is the base class
|
||||
* for a family of classes that compute properties of a set of
|
||||
* species in their reference state at a range of temperatures.
|
||||
* Note, the pressure dependence of the reference state is not
|
||||
* handled by this particular species standard state model.
|
||||
*/
|
||||
class SpeciesThermo {
|
||||
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
SpeciesThermo() {}
|
||||
|
||||
//! Destructor
|
||||
virtual ~SpeciesThermo() {}
|
||||
|
||||
|
||||
//! Install a new species thermodynamic property
|
||||
//! parameterization for one species.
|
||||
/*!
|
||||
*
|
||||
* @param name Name of the species
|
||||
* @param index The 'update' method will update the property
|
||||
* values for this species
|
||||
* at position i index in the property arrays.
|
||||
* @param type int flag specifying the type of parameterization to be
|
||||
* installed.
|
||||
* @param c vector of coefficients for the parameterization.
|
||||
* This vector is simply passed through to the
|
||||
* parameterization constructor.
|
||||
* @param minTemp minimum temperature for which this parameterization
|
||||
* is valid.
|
||||
* @param maxTemp maximum temperature for which this parameterization
|
||||
* is valid.
|
||||
* @param refPressure standard-state pressure for this
|
||||
* parameterization.
|
||||
* @see speciesThermoTypes.h
|
||||
*/
|
||||
virtual void install(std::string name, int index, int type,
|
||||
const doublereal* c,
|
||||
doublereal minTemp,
|
||||
doublereal maxTemp,
|
||||
doublereal refPressure)=0;
|
||||
|
||||
|
||||
//! Compute the reference-state properties for all species.
|
||||
/*!
|
||||
* Given temperature T in K, this method updates the values of
|
||||
* the non-dimensional heat capacity at constant pressure,
|
||||
* enthalpy, and entropy, at the reference pressure, Pref
|
||||
* of each of the standard states.
|
||||
*
|
||||
* @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).
|
||||
*/
|
||||
virtual void update(doublereal T,
|
||||
doublereal* cp_R,
|
||||
doublereal* h_RT,
|
||||
doublereal* s_R) const=0;
|
||||
|
||||
|
||||
//! 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).
|
||||
*
|
||||
*/
|
||||
virtual void update_one(int k, doublereal T,
|
||||
doublereal* cp_R,
|
||||
doublereal* h_RT,
|
||||
doublereal* s_R) const {
|
||||
update(T, cp_R, h_RT, s_R);
|
||||
}
|
||||
|
||||
//! Minimum temperature.
|
||||
/*!
|
||||
* If no argument is supplied, this
|
||||
* method returns the minimum temperature for which \e all
|
||||
* parameterizations are valid. If an integer index k is
|
||||
* supplied, then the value returned is the minimum
|
||||
* temperature for species k in the phase.
|
||||
*
|
||||
* @param k Species index
|
||||
*/
|
||||
virtual doublereal minTemp(int k=-1) const =0;
|
||||
|
||||
//! Maximum temperature.
|
||||
/*!
|
||||
* If no argument is supplied, this
|
||||
* method returns the maximum temperature for which \e all
|
||||
* parameterizations are valid. If an integer index k is
|
||||
* supplied, then the value returned is the maximum
|
||||
* temperature for parameterization k.
|
||||
*
|
||||
* @param k Species Index
|
||||
*/
|
||||
virtual doublereal maxTemp(int k=-1) const =0;
|
||||
|
||||
//! The reference-state pressure for species k.
|
||||
/*!
|
||||
*
|
||||
* returns the reference state pressure in Pascals for
|
||||
* species k. If k is left out of the argument list,
|
||||
* it returns the reference state pressure for the first
|
||||
* species.
|
||||
* Note that some SpeciesThermo implementations, such
|
||||
* as those for ideal gases, require that all species
|
||||
* in the same phase have the same reference state pressures.
|
||||
*
|
||||
* @param k Species Index
|
||||
*/
|
||||
virtual doublereal refPressure(int k=-1) const =0;
|
||||
|
||||
//! This utility function reports the type of parameterization
|
||||
//! used for the species with index number index.
|
||||
/*!
|
||||
*
|
||||
* @param index Species index
|
||||
*/
|
||||
virtual int reportType(int index = -1) const = 0;
|
||||
|
||||
|
||||
//! This utility function reports back the type of
|
||||
//! parameterization and all of the parameters for the species, index.
|
||||
/*!
|
||||
* @param index Species index
|
||||
* @param type Integer type of the standard type
|
||||
* @param c Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
* @param minTemp output - Minimum temperature
|
||||
* @param maxTemp output - Maximum temperature
|
||||
* @param refPressure output - reference pressure (Pa).
|
||||
*/
|
||||
virtual void reportParams(int index, int &type,
|
||||
doublereal * const c,
|
||||
doublereal &minTemp,
|
||||
doublereal &maxTemp,
|
||||
doublereal &refPressure) const =0;
|
||||
|
||||
//! Modify parameters for the standard state
|
||||
/*!
|
||||
* @param index Species index
|
||||
* @param c Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
*/
|
||||
virtual void modifyParams(int index, doublereal *c) = 0;
|
||||
|
||||
};
|
||||
//@}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
488
Cantera/src/thermo/SpeciesThermoFactory.cpp
Executable file
488
Cantera/src/thermo/SpeciesThermoFactory.cpp
Executable file
|
|
@ -0,0 +1,488 @@
|
|||
/**
|
||||
* @file SpeciesThermoFactory.cpp
|
||||
* Definitions for factory to build instances of classes that manage the
|
||||
* standard-state thermodynamic properties of a set of species
|
||||
* (see \ref spthermo and class \link Cantera::SpeciesThermoFactory SpeciesThermoFactory\endlink);
|
||||
*/
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
// Copyright 2001 California Institute of Technology
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma warning(disable:4786)
|
||||
#endif
|
||||
|
||||
|
||||
#include "SpeciesThermoFactory.h"
|
||||
using namespace std;
|
||||
|
||||
#include "SpeciesThermo.h"
|
||||
#include "NasaThermo.h"
|
||||
#include "ShomateThermo.h"
|
||||
#include "SimpleThermo.h"
|
||||
#include "GeneralSpeciesThermo.h"
|
||||
#include "Mu0Poly.h"
|
||||
|
||||
#include "SpeciesThermoMgr.h"
|
||||
#include "speciesThermoTypes.h"
|
||||
|
||||
#include "xml.h"
|
||||
#include "ctml.h"
|
||||
|
||||
using namespace ctml;
|
||||
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
SpeciesThermoFactory* SpeciesThermoFactory::s_factory = 0;
|
||||
|
||||
/**
|
||||
* Examine the types of species thermo parameterizations,
|
||||
* and return a flag indicating the type of parameterization
|
||||
* needed by the species.
|
||||
*
|
||||
* @param spData_node Species Data XML node. This node contains a list
|
||||
* of species XML nodes underneath it.
|
||||
*
|
||||
* @todo Make sure that spDadta_node is species Data XML node by checking its name is speciesData
|
||||
*/
|
||||
static void getSpeciesThermoTypes(XML_Node* spData_node,
|
||||
int& has_nasa, int& has_shomate, int& has_simple,
|
||||
int &has_other) {
|
||||
const XML_Node& sparray = *spData_node;
|
||||
std::vector<XML_Node*> sp;
|
||||
|
||||
// get all of the species nodes
|
||||
sparray.getChildren("species",sp);
|
||||
size_t n, ns = sp.size();
|
||||
for (n = 0; n < ns; n++) {
|
||||
XML_Node* spNode = sp[n];
|
||||
if (spNode->hasChild("thermo")) {
|
||||
const XML_Node& th = sp[n]->child("thermo");
|
||||
if (th.hasChild("NASA")) has_nasa = 1;
|
||||
if (th.hasChild("Shomate")) has_shomate = 1;
|
||||
if (th.hasChild("const_cp")) has_simple = 1;
|
||||
if (th.hasChild("poly")) {
|
||||
if (th.child("poly")["order"] == "1") has_simple = 1;
|
||||
else throw CanteraError("newSpeciesThermo",
|
||||
"poly with order > 1 not yet supported");
|
||||
}
|
||||
if (th.hasChild("Mu0")) has_other = 1;
|
||||
} else {
|
||||
throw UnknownSpeciesThermoModel("getSpeciesThermoTypes:",
|
||||
spNode->attrib("name"), "missing");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a species thermo manager to handle the parameterizations
|
||||
* specified in a CTML phase specification.
|
||||
*/
|
||||
SpeciesThermo* SpeciesThermoFactory::newSpeciesThermo(XML_Node* spData_node) {
|
||||
int inasa = 0, ishomate = 0, isimple = 0, iother = 0;
|
||||
try {
|
||||
getSpeciesThermoTypes(spData_node, inasa, ishomate, isimple, iother);
|
||||
} catch (UnknownSpeciesThermoModel) {
|
||||
iother = 1;
|
||||
popError();
|
||||
}
|
||||
if (iother) {
|
||||
writelog("returning new GeneralSpeciesThermo");
|
||||
return new GeneralSpeciesThermo();
|
||||
}
|
||||
return newSpeciesThermo(NASA*inasa
|
||||
+ SHOMATE*ishomate + SIMPLE*isimple);
|
||||
}
|
||||
|
||||
SpeciesThermo* SpeciesThermoFactory::
|
||||
newSpeciesThermo(std::vector<XML_Node*> spData_nodes) {
|
||||
int n = static_cast<int>(spData_nodes.size());
|
||||
int inasa = 0, ishomate = 0, isimple = 0, iother = 0;
|
||||
for (int j = 0; j < n; j++) {
|
||||
try {
|
||||
getSpeciesThermoTypes(spData_nodes[j], inasa, ishomate, isimple, iother);
|
||||
} catch (UnknownSpeciesThermoModel) {
|
||||
iother = 1;
|
||||
popError();
|
||||
}
|
||||
}
|
||||
if (iother) {
|
||||
return new GeneralSpeciesThermo();
|
||||
}
|
||||
return newSpeciesThermo(NASA*inasa
|
||||
+ SHOMATE*ishomate + SIMPLE*isimple);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @todo is this used?
|
||||
*/
|
||||
SpeciesThermo* SpeciesThermoFactory::
|
||||
newSpeciesThermoOpt(std::vector<XML_Node*> nodes) {
|
||||
int n = static_cast<int>(nodes.size());
|
||||
int inasa = 0, ishomate = 0, isimple = 0, iother = 0;
|
||||
for (int j = 0; j < n; j++) {
|
||||
try {
|
||||
getSpeciesThermoTypes(nodes[j], inasa, ishomate, isimple, iother);
|
||||
} catch (UnknownSpeciesThermoModel) {
|
||||
iother = 1;
|
||||
popError();
|
||||
}
|
||||
}
|
||||
if (iother) {
|
||||
return new GeneralSpeciesThermo();
|
||||
}
|
||||
return newSpeciesThermo(NASA*inasa
|
||||
+ SHOMATE*ishomate + SIMPLE*isimple);
|
||||
}
|
||||
|
||||
|
||||
|
||||
SpeciesThermo* SpeciesThermoFactory::newSpeciesThermo(int type) {
|
||||
|
||||
switch (type) {
|
||||
case NASA:
|
||||
return new NasaThermo;
|
||||
case SHOMATE:
|
||||
return new ShomateThermo;
|
||||
case SIMPLE:
|
||||
return new SimpleThermo;
|
||||
case NASA + SHOMATE:
|
||||
return new SpeciesThermoDuo<NasaThermo, ShomateThermo>;
|
||||
case NASA + SIMPLE:
|
||||
return new SpeciesThermoDuo<NasaThermo, SimpleThermo>;
|
||||
case SHOMATE + SIMPLE:
|
||||
return new SpeciesThermoDuo<ShomateThermo, SimpleThermo>;
|
||||
default:
|
||||
throw UnknownSpeciesThermo(
|
||||
"SpeciesThermoFactory::newSpeciesThermo",type);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check the continuity of properties at the midpoint
|
||||
* temperature.
|
||||
*/
|
||||
void NasaThermo::checkContinuity(std::string name, double tmid, const doublereal* clow,
|
||||
doublereal* chigh) {
|
||||
|
||||
// heat capacity
|
||||
doublereal cplow = poly4(tmid, clow);
|
||||
doublereal cphigh = poly4(tmid, chigh);
|
||||
doublereal delta = cplow - cphigh;
|
||||
if (fabs(delta/cplow) > 0.001) {
|
||||
writelog("\n\n**** WARNING ****\nFor species "+name+
|
||||
", discontinuity in cp/R detected at Tmid = "
|
||||
+fp2str(tmid)+"\n");
|
||||
writelog("\tValue computed using low-temperature polynomial: "
|
||||
+fp2str(cplow)+".\n");
|
||||
writelog("\tValue computed using high-temperature polynomial: "
|
||||
+fp2str(cphigh)+".\n");
|
||||
}
|
||||
|
||||
// enthalpy
|
||||
doublereal hrtlow = enthalpy_RT(tmid, clow);
|
||||
doublereal hrthigh = enthalpy_RT(tmid, chigh);
|
||||
delta = hrtlow - hrthigh;
|
||||
if (fabs(delta/hrtlow) > 0.001) {
|
||||
writelog("\n\n**** WARNING ****\nFor species "+name+
|
||||
", discontinuity in h/RT detected at Tmid = "
|
||||
+fp2str(tmid)+"\n");
|
||||
writelog("\tValue computed using low-temperature polynomial: "
|
||||
+fp2str(hrtlow)+".\n");
|
||||
writelog("\tValue computed using high-temperature polynomial: "
|
||||
+fp2str(hrthigh)+".\n");
|
||||
}
|
||||
|
||||
// entropy
|
||||
doublereal srlow = entropy_R(tmid, clow);
|
||||
doublereal srhigh = entropy_R(tmid, chigh);
|
||||
delta = srlow - srhigh;
|
||||
if (fabs(delta/srlow) > 0.001) {
|
||||
writelog("\n\n**** WARNING ****\nFor species "+name+
|
||||
", discontinuity in s/R detected at Tmid = "
|
||||
+fp2str(tmid)+"\n");
|
||||
writelog("\tValue computed using low-temperature polynomial: "
|
||||
+fp2str(srlow)+".\n");
|
||||
writelog("\tValue computed using high-temperature polynomial: "
|
||||
+fp2str(srhigh)+".\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Install a NASA polynomial thermodynamic property
|
||||
* parameterization for species k into a SpeciesThermo instance.
|
||||
* This is called by method installThermoForSpecies if a NASA
|
||||
* block is found in the XML input.
|
||||
*/
|
||||
static void installNasaThermoFromXML(std::string speciesName,
|
||||
SpeciesThermo& sp, int k,
|
||||
const XML_Node* f0ptr, const XML_Node* f1ptr) {
|
||||
doublereal tmin0, tmax0, tmin1, tmax1, tmin, tmid, tmax;
|
||||
|
||||
const XML_Node& f0 = *f0ptr;
|
||||
|
||||
// default to a single temperature range
|
||||
bool dualRange = false;
|
||||
|
||||
// but if f1ptr is suppled, then it is a two-range
|
||||
// parameterization
|
||||
if (f1ptr) {dualRange = true;}
|
||||
|
||||
tmin0 = fpValue(f0["Tmin"]);
|
||||
tmax0 = fpValue(f0["Tmax"]);
|
||||
tmin1 = tmax0;
|
||||
tmax1 = tmin1 + 0.0001;
|
||||
if (dualRange) {
|
||||
tmin1 = fpValue((*f1ptr)["Tmin"]);
|
||||
tmax1 = fpValue((*f1ptr)["Tmax"]);
|
||||
}
|
||||
|
||||
vector_fp c0, c1;
|
||||
if (fabs(tmax0 - tmin1) < 0.01) {
|
||||
// f0 has the lower T data, and f1 the higher T data
|
||||
tmin = tmin0;
|
||||
tmid = tmax0;
|
||||
tmax = tmax1;
|
||||
getFloatArray(f0.child("floatArray"), c0, false);
|
||||
if (dualRange)
|
||||
getFloatArray(f1ptr->child("floatArray"), c1, false);
|
||||
else {
|
||||
// if there is no higher range data, then copy c0 to c1.
|
||||
c1.resize(7,0.0);
|
||||
copy(c0.begin(), c0.end(), c1.begin());
|
||||
}
|
||||
}
|
||||
else if (fabs(tmax1 - tmin0) < 0.01) {
|
||||
// f1 has the lower T data, and f0 the higher T data
|
||||
tmin = tmin1;
|
||||
tmid = tmax1;
|
||||
tmax = tmax0;
|
||||
getFloatArray(f1ptr->child("floatArray"), c0, false);
|
||||
getFloatArray(f0.child("floatArray"), c1, false);
|
||||
}
|
||||
else {
|
||||
throw CanteraError("installNasaThermo",
|
||||
"non-continuous temperature ranges.");
|
||||
}
|
||||
|
||||
// The NasaThermo species property manager expects the
|
||||
// coefficients in a different order, so rearrange them.
|
||||
array_fp c(15);
|
||||
c[0] = tmid;
|
||||
doublereal p0 = OneAtm;
|
||||
c[1] = c0[5];
|
||||
c[2] = c0[6];
|
||||
copy(c0.begin(), c0.begin()+5, c.begin() + 3);
|
||||
c[8] = c1[5];
|
||||
c[9] = c1[6];
|
||||
copy(c1.begin(), c1.begin()+5, c.begin() + 10);
|
||||
sp.install(speciesName, k, NASA, &c[0], tmin, tmax, p0);
|
||||
}
|
||||
|
||||
#ifdef INCL_NASA96
|
||||
|
||||
/**
|
||||
* Install a NASA96 polynomial thermodynamic property
|
||||
* parameterization for species k into a SpeciesThermo instance.
|
||||
*/
|
||||
static void installNasa96ThermoFromXML(std::string speciesName,
|
||||
SpeciesThermo& sp, int k,
|
||||
const XML_Node* f0ptr, const XML_Node* f1ptr) {
|
||||
doublereal tmin0, tmax0, tmin1, tmax1, tmin, tmid, tmax;
|
||||
|
||||
const XML_Node& f0 = *f0ptr;
|
||||
bool dualRange = false;
|
||||
if (f1ptr) {dualRange = true;}
|
||||
tmin0 = fpValue(f0["Tmin"]);
|
||||
tmax0 = fpValue(f0["Tmax"]);
|
||||
tmin1 = tmax0;
|
||||
tmax1 = tmin1 + 0.0001;
|
||||
if (dualRange) {
|
||||
tmin1 = fpValue((*f1ptr)["Tmin"]);
|
||||
tmax1 = fpValue((*f1ptr)["Tmax"]);
|
||||
}
|
||||
|
||||
vector_fp c0, c1;
|
||||
if (fabs(tmax0 - tmin1) < 0.01) {
|
||||
tmin = tmin0;
|
||||
tmid = tmax0;
|
||||
tmax = tmax1;
|
||||
getFloatArray(f0.child("floatArray"), c0, false);
|
||||
if (dualRange)
|
||||
getFloatArray(f1ptr->child("floatArray"), c1, false);
|
||||
else {
|
||||
c1.resize(7,0.0);
|
||||
copy(c0.begin(), c0.end(), c1.begin());
|
||||
}
|
||||
}
|
||||
else if (fabs(tmax1 - tmin0) < 0.01) {
|
||||
tmin = tmin1;
|
||||
tmid = tmax1;
|
||||
tmax = tmax0;
|
||||
getFloatArray(f1ptr->child("floatArray"), c0, false);
|
||||
getFloatArray(f0.child("floatArray"), c1, false);
|
||||
}
|
||||
else {
|
||||
throw CanteraError("installNasaThermo",
|
||||
"non-continuous temperature ranges.");
|
||||
}
|
||||
array_fp c(15);
|
||||
c[0] = tmid;
|
||||
doublereal p0 = OneAtm;
|
||||
c[1] = c0[5];
|
||||
c[2] = c0[6];
|
||||
copy(c0.begin(), c0.begin()+5, c.begin() + 3);
|
||||
c[8] = c1[5];
|
||||
c[9] = c1[6];
|
||||
copy(c1.begin(), c1.begin()+5, c.begin() + 10);
|
||||
sp.install(speciesName, k, NASA, &c[0], tmin, tmax, p0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Install a Shomate polynomial thermodynamic property
|
||||
* parameterization for species k.
|
||||
*/
|
||||
static void installShomateThermoFromXML(std::string speciesName,
|
||||
SpeciesThermo& sp, int k,
|
||||
const XML_Node* f0ptr, const XML_Node* f1ptr) {
|
||||
doublereal tmin0, tmax0, tmin1, tmax1, tmin, tmid, tmax;
|
||||
|
||||
const XML_Node& f0 = *f0ptr;
|
||||
bool dualRange = false;
|
||||
if (f1ptr) {dualRange = true;}
|
||||
tmin0 = fpValue(f0["Tmin"]);
|
||||
tmax0 = fpValue(f0["Tmax"]);
|
||||
tmin1 = tmax0;
|
||||
tmax1 = tmin1 + 0.0001;
|
||||
if (dualRange) {
|
||||
tmin1 = fpValue((*f1ptr)["Tmin"]);
|
||||
tmax1 = fpValue((*f1ptr)["Tmax"]);
|
||||
}
|
||||
|
||||
vector_fp c0, c1;
|
||||
if (fabs(tmax0 - tmin1) < 0.01) {
|
||||
tmin = tmin0;
|
||||
tmid = tmax0;
|
||||
tmax = tmax1;
|
||||
getFloatArray(f0.child("floatArray"), c0, false);
|
||||
if (dualRange)
|
||||
getFloatArray(f1ptr->child("floatArray"), c1, false);
|
||||
else {
|
||||
c1.resize(7,0.0);
|
||||
copy(c0.begin(), c0.begin()+7, c1.begin());
|
||||
}
|
||||
}
|
||||
else if (fabs(tmax1 - tmin0) < 0.01) {
|
||||
tmin = tmin1;
|
||||
tmid = tmax1;
|
||||
tmax = tmax0;
|
||||
getFloatArray(f1ptr->child("floatArray"), c0, false);
|
||||
getFloatArray(f0.child("floatArray"), c1, false);
|
||||
}
|
||||
else {
|
||||
throw CanteraError("installShomateThermo",
|
||||
"non-continuous temperature ranges.");
|
||||
}
|
||||
array_fp c(15);
|
||||
c[0] = tmid;
|
||||
doublereal p0 = OneAtm;
|
||||
copy(c0.begin(), c0.begin()+7, c.begin() + 1);
|
||||
copy(c1.begin(), c1.begin()+7, c.begin() + 8);
|
||||
sp.install(speciesName, k, SHOMATE, &c[0], tmin, tmax, p0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Install a constant-cp thermodynamic property
|
||||
* parameterization for species k.
|
||||
*/
|
||||
static void installSimpleThermoFromXML(std::string speciesName,
|
||||
SpeciesThermo& sp, int k,
|
||||
const XML_Node& f) {
|
||||
doublereal tmin, tmax;
|
||||
tmin = fpValue(f["Tmin"]);
|
||||
tmax = fpValue(f["Tmax"]);
|
||||
if (tmax == 0.0) tmax = 1.0e30;
|
||||
|
||||
vector_fp c(4);
|
||||
c[0] = getFloat(f, "t0", "-");
|
||||
c[1] = getFloat(f, "h0", "-");
|
||||
c[2] = getFloat(f, "s0", "-");
|
||||
c[3] = getFloat(f, "cp0", "-");
|
||||
doublereal p0 = OneAtm;
|
||||
sp.install(speciesName, k, SIMPLE, &c[0], tmin, tmax, p0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Install a species thermodynamic property parameterization
|
||||
* for one species into a species thermo manager.
|
||||
* @param k species number
|
||||
* @param s XML node specifying species
|
||||
* @param spthermo species thermo manager
|
||||
*/
|
||||
void SpeciesThermoFactory::
|
||||
installThermoForSpecies(int k, const XML_Node& s,
|
||||
SpeciesThermo& spthermo) {
|
||||
/*
|
||||
* Check to see that the species block has a thermo block
|
||||
* before processing. Throw an error if not there.
|
||||
*/
|
||||
if (!(s.hasChild("thermo"))) {
|
||||
throw UnknownSpeciesThermoModel("installSpecies",
|
||||
s["name"], "<nonexistent>");
|
||||
}
|
||||
const XML_Node& thermo = s.child("thermo");
|
||||
const std::vector<XML_Node*>& tp = thermo.children();
|
||||
int nc = static_cast<int>(tp.size());
|
||||
if (nc == 1) {
|
||||
const XML_Node* f = tp[0];
|
||||
if (f->name() == "Shomate") {
|
||||
installShomateThermoFromXML(s["name"], spthermo, k, f, 0);
|
||||
}
|
||||
else if (f->name() == "const_cp") {
|
||||
installSimpleThermoFromXML(s["name"], spthermo, k, *f);
|
||||
}
|
||||
else if (f->name() == "NASA") {
|
||||
installNasaThermoFromXML(s["name"], spthermo, k, f, 0);
|
||||
}
|
||||
else if (f->name() == "Mu0") {
|
||||
installMu0ThermoFromXML(s["name"], spthermo, k, f);
|
||||
}
|
||||
else {
|
||||
throw UnknownSpeciesThermoModel("installSpecies",
|
||||
s["name"], f->name());
|
||||
}
|
||||
}
|
||||
else if (nc == 2) {
|
||||
const XML_Node* f0 = tp[0];
|
||||
const XML_Node* f1 = tp[1];
|
||||
if (f0->name() == "NASA" && f1->name() == "NASA") {
|
||||
installNasaThermoFromXML(s["name"], spthermo, k, f0, f1);
|
||||
}
|
||||
else if (f0->name() == "Shomate" && f1->name() == "Shomate") {
|
||||
installShomateThermoFromXML(s["name"], spthermo, k, f0, f1);
|
||||
}
|
||||
else {
|
||||
throw UnknownSpeciesThermoModel("installSpecies", s["name"],
|
||||
f0->name() + " and "
|
||||
+ f1->name());
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw UnknownSpeciesThermoModel("installSpecies", s["name"],
|
||||
"multiple");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
252
Cantera/src/thermo/SpeciesThermoFactory.h
Executable file
252
Cantera/src/thermo/SpeciesThermoFactory.h
Executable file
|
|
@ -0,0 +1,252 @@
|
|||
/**
|
||||
* @file SpeciesThermoFactory.h
|
||||
* Header for factory to build instances of classes that manage the
|
||||
* standard-state thermodynamic properties of a set of species
|
||||
* (see \ref spthermo and class \link Cantera::SpeciesThermoFactory SpeciesThermoFactory\endlink);
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
// Copyright 2001 California Institute of Technology
|
||||
|
||||
|
||||
#ifndef SPECIESTHERMO_FACTORY_H
|
||||
#define SPECIESTHERMO_FACTORY_H
|
||||
|
||||
#include "SpeciesThermo.h"
|
||||
#include "ctexceptions.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
class XML_Node;
|
||||
|
||||
/**
|
||||
* Throw a named error for an unknown or missing species thermo model.
|
||||
*
|
||||
* @ingroup thermoprops
|
||||
*/
|
||||
class UnknownSpeciesThermoModel: public CanteraError {
|
||||
public:
|
||||
//! constructor
|
||||
/*!
|
||||
* @param proc Function name error occurred.
|
||||
* @param spName Species Name that caused the error
|
||||
* @param speciesThermoModel Unrecognized species thermo model name
|
||||
*/
|
||||
UnknownSpeciesThermoModel(std::string proc, std::string spName,
|
||||
std::string speciesThermoModel) :
|
||||
CanteraError(proc, "species " + spName +
|
||||
": Specified speciesThermoPhase model "
|
||||
+ speciesThermoModel +
|
||||
" does not match any known type.") {}
|
||||
//! destructor
|
||||
virtual ~UnknownSpeciesThermoModel() {}
|
||||
};
|
||||
|
||||
//! Factory to build instances of classes that manage the
|
||||
//! standard-state thermodynamic properties of a set of species.
|
||||
/*!
|
||||
* This class is implemented as a singleton -- one in which
|
||||
* only one instance is needed. The recommended way to access
|
||||
* the factory is to call this static method, which
|
||||
* instantiates the class if it is the first call, but
|
||||
* otherwise simply returns the pointer to the existing
|
||||
* instance.
|
||||
*
|
||||
* @ingroup thermoprops
|
||||
*/
|
||||
class SpeciesThermoFactory {
|
||||
|
||||
public:
|
||||
|
||||
//! Static method to return an instance of this class
|
||||
/*!
|
||||
* This class is implemented as a singleton -- one in which
|
||||
* only one instance is needed. The recommended way to access
|
||||
* the factory is to call this static method, which
|
||||
* instantiates the class if it is the first call, but
|
||||
* otherwise simply returns the pointer to the existing
|
||||
* instance.
|
||||
*/
|
||||
static SpeciesThermoFactory* factory() {
|
||||
if (!s_factory) s_factory = new SpeciesThermoFactory;
|
||||
return s_factory;
|
||||
}
|
||||
|
||||
//! Delete static instance of this class
|
||||
/**
|
||||
* If it is necessary to explicitly delete the factory before
|
||||
* the process terminates (for example, when checking for
|
||||
* memory leaks) then this method can be called to delete it.
|
||||
*/
|
||||
static void deleteFactory() {
|
||||
if (s_factory) {
|
||||
delete s_factory;
|
||||
s_factory = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
/**
|
||||
* Doesn't do anything. We do not delete statically
|
||||
* created single instance of this class here, because it would
|
||||
* create an infinite loop if destructor is called for that
|
||||
* single instance.
|
||||
*/
|
||||
virtual ~SpeciesThermoFactory() {
|
||||
}
|
||||
|
||||
//! Create a new species property manager.
|
||||
/*!
|
||||
* @param type the integer type to be created.
|
||||
*/
|
||||
virtual SpeciesThermo* newSpeciesThermo(int type);
|
||||
|
||||
//! Create a new species property manager.
|
||||
/*!
|
||||
* This routine will look through species nodes. It will discover what
|
||||
* each species needs for its species property managers. Then,
|
||||
* it will malloc and return the proper species property manager to use.
|
||||
*
|
||||
* @param spData_node Pointer to a speciesData XML Node.
|
||||
* Each speciesData node contains a list of XML species elements
|
||||
* e.g., \<speciesData id="Species_Data"\>
|
||||
*/
|
||||
virtual SpeciesThermo* newSpeciesThermo(XML_Node* spData_node);
|
||||
|
||||
//! Create a new species property manager for a group of species
|
||||
/*!
|
||||
* This routine will look through species nodes. It will discover what
|
||||
* each species needs for its species property managers. Then,
|
||||
* it will malloc and return the proper species property manager to use.
|
||||
*
|
||||
* @param spData_nodes Vector of XML_Nodes, each of which is a speciesData XML Node.
|
||||
* Each speciesData node contains a list of XML species elements
|
||||
* e.g., \<speciesData id="Species_Data"\>
|
||||
*/
|
||||
virtual SpeciesThermo* newSpeciesThermo(std::vector<XML_Node*> spData_nodes);
|
||||
|
||||
//! Create a new species property manager.
|
||||
/*!
|
||||
* This routine will look through species nodes. It will discover what
|
||||
* each species needs for its species property managers. Then,
|
||||
* it will malloc and return the proper species property manager to use.
|
||||
*
|
||||
*
|
||||
* @param spData_nodes Vector of XML_Nodes, each of which is a speciesData XML Node.
|
||||
* Each %speciesData node contains a list of XML species elements
|
||||
* e.g., \<speciesData id="Species_Data"\>
|
||||
*
|
||||
* @todo is this used?
|
||||
*/
|
||||
virtual SpeciesThermo* newSpeciesThermoOpt(std::vector<XML_Node*> spData_nodes);
|
||||
|
||||
|
||||
virtual void installThermoForSpecies(int k, const XML_Node& s,
|
||||
SpeciesThermo& spthermo);
|
||||
|
||||
private:
|
||||
|
||||
//! pointer to the sole instance of this class
|
||||
static SpeciesThermoFactory* s_factory;
|
||||
|
||||
//! Constructor. This is made private, so that only the static
|
||||
//! method factory() can instantiate the class.
|
||||
SpeciesThermoFactory(){}
|
||||
};
|
||||
|
||||
|
||||
////////////////////// Convenience functions ////////////////////
|
||||
//
|
||||
// These functions allow using a different factory class that
|
||||
// derives from SpeciesThermoFactory.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
//! Create a new species thermo manager instance, by specifying
|
||||
//!the type and (optionally) a pointer to the factory to use to create it.
|
||||
/*!
|
||||
* This utility program will look through species nodes. It will discover what
|
||||
* each species needs for its species property managers. Then,
|
||||
* it will malloc and return the proper species property manager to use.
|
||||
*
|
||||
* These functions allow using a different factory class that
|
||||
* derives from SpeciesThermoFactory.
|
||||
*
|
||||
* @param type Species thermo type.
|
||||
* @param f Pointer to a SpeciesThermoFactory. optional parameter.
|
||||
* Defautls to NULL.
|
||||
*/
|
||||
inline SpeciesThermo* newSpeciesThermoMgr(int type,
|
||||
SpeciesThermoFactory* f=0) {
|
||||
if (f == 0) {
|
||||
f = SpeciesThermoFactory::factory();
|
||||
}
|
||||
SpeciesThermo* sptherm = f->newSpeciesThermo(type);
|
||||
return sptherm;
|
||||
}
|
||||
|
||||
//! Function to return SpeciesThermo manager
|
||||
/*!
|
||||
* This utility program will look through species nodes. It will discover what
|
||||
* each species needs for its species property managers. Then,
|
||||
* it will malloc and return the proper species property manager to use.
|
||||
*
|
||||
* These functions allow using a different factory class that
|
||||
* derives from SpeciesThermoFactory.
|
||||
*
|
||||
* @param spData_node Vector of XML_Nodes, each of which is a speciesData XML Node.
|
||||
* Each %speciesData node contains a list of XML species elements
|
||||
* e.g., \<speciesData id="Species_Data"\>
|
||||
* @param f Pointer to a SpeciesThermoFactory. optional parameter.
|
||||
* Defautls to NULL.
|
||||
*/
|
||||
inline SpeciesThermo* newSpeciesThermoMgr(XML_Node* spData_node,
|
||||
SpeciesThermoFactory* f=0) {
|
||||
if (f == 0) {
|
||||
f = SpeciesThermoFactory::factory();
|
||||
}
|
||||
SpeciesThermo* sptherm = f->newSpeciesThermo(spData_node);
|
||||
return sptherm;
|
||||
}
|
||||
|
||||
//! Function to return SpeciesThermo manager
|
||||
/*!
|
||||
* This utility program will look through species nodes. It will discover what
|
||||
* each species needs for its species property managers. Then,
|
||||
* it will malloc and return the proper species property manager to use.
|
||||
*
|
||||
* These functions allow using a different factory class that
|
||||
* derives from SpeciesThermoFactory.
|
||||
*
|
||||
* @param spData_nodes Vector of XML_Nodes, each of which is a speciesData XML Node.
|
||||
* Each %speciesData node contains a list of XML species elements
|
||||
* e.g., \<speciesData id="Species_Data"\>
|
||||
* @param f Pointer to a SpeciesThermoFactory. optional parameter.
|
||||
* Defautls to NULL.
|
||||
* @param opt Boolean defaults to false.
|
||||
*/
|
||||
inline SpeciesThermo* newSpeciesThermoMgr(std::vector<XML_Node*> spData_nodes,
|
||||
SpeciesThermoFactory* f=0, bool opt=false) {
|
||||
if (f == 0) {
|
||||
f = SpeciesThermoFactory::factory();
|
||||
}
|
||||
SpeciesThermo* sptherm;
|
||||
if (opt) {
|
||||
sptherm = f->newSpeciesThermoOpt(spData_nodes);
|
||||
} else {
|
||||
sptherm = f->newSpeciesThermo(spData_nodes);
|
||||
}
|
||||
return sptherm;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
150
Cantera/src/thermo/SpeciesThermoInterpType.h
Normal file
150
Cantera/src/thermo/SpeciesThermoInterpType.h
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
/**
|
||||
* @file SpeciesThermoInterpType.h
|
||||
* Pure Virtual Base class for individual species reference state
|
||||
* themodynamic managers (see \ref spthermo and class \link Cantera::SpeciesThermoInterpType SpeciesThermoInterpType \endlink).
|
||||
*/
|
||||
/*
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
// Copyright 2001 California Institute of Technology
|
||||
|
||||
#include "speciesThermoTypes.h"
|
||||
|
||||
#ifndef CT_SPECIESTHERMOINTERPTYPE_H
|
||||
#define CT_SPECIESTHERMOINTERPTYPE_H
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
//! Pure Virtual Base class for individual species reference state
|
||||
//! themodynamic managers.
|
||||
/*!
|
||||
* This differs from the SpeciesThermo virtual
|
||||
* base class in the sense that this class is meant to handle only
|
||||
* one species. The speciesThermo class is meant to handle the
|
||||
* calculation of all the species (or a large subset) in a phase.
|
||||
*
|
||||
* One key feature is that the update routines use the same
|
||||
* form as the update routines in the speciesThermo class. They update
|
||||
* into a vector of cp_R, s_R, and H_R that spans all of the species in
|
||||
* a phase. Therefore, this class must carry along a species index into that
|
||||
* vector.
|
||||
*
|
||||
* These routine may be templated. A key requirement of the template is that
|
||||
* there is a constructor with the following form:
|
||||
*
|
||||
* @code
|
||||
* SpeciesThermoInterpType(int index, doublereal tlow, doublereal thigh,
|
||||
* doublereal pref, const doublereal* coeffs)
|
||||
* @endcode
|
||||
*
|
||||
* The constructor is used to instantiate the object.
|
||||
*
|
||||
* @ingroup spthermo
|
||||
*/
|
||||
class SpeciesThermoInterpType {
|
||||
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
SpeciesThermoInterpType() {};
|
||||
|
||||
//! Destructor
|
||||
virtual ~SpeciesThermoInterpType() {};
|
||||
|
||||
//! duplicator
|
||||
virtual SpeciesThermoInterpType *
|
||||
duplMyselfAsSpeciesThermoInterpType() const = 0;
|
||||
|
||||
|
||||
//! Returns the minimum temperature that the thermo
|
||||
//! parameterization is valid
|
||||
virtual doublereal minTemp() const = 0;
|
||||
|
||||
//! Returns the maximum temperature that the thermo
|
||||
//! parameterization is valid
|
||||
virtual doublereal maxTemp() const = 0;
|
||||
|
||||
//! Returns the reference pressure (Pa)
|
||||
virtual doublereal refPressure() const = 0;
|
||||
|
||||
//! Returns an integer representing the type of parameterization
|
||||
virtual int reportType() const = 0;
|
||||
|
||||
//! Update the properties for this species, given a temperature polynomial
|
||||
/*!
|
||||
* This method is called with a pointer to an array containing the functions of
|
||||
* temperature needed by this parameterization, and three pointers to arrays where the
|
||||
* computed property values should be written. This method updates only one value in
|
||||
* each array.
|
||||
*
|
||||
* The form and length of the Temperature Polynomial may vary depending on the
|
||||
* parameterization.
|
||||
*
|
||||
* @param tempPoly vector of temperature polynomials
|
||||
* @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).
|
||||
*/
|
||||
virtual void updateProperties(const doublereal* tempPoly,
|
||||
doublereal* cp_R, doublereal* h_RT,
|
||||
doublereal* s_R) const = 0;
|
||||
|
||||
//! Compute the reference-state property of one species
|
||||
/*!
|
||||
* Given temperature T in K, this method updates the values of
|
||||
* the non-dimensional heat capacity at constant pressure,
|
||||
* enthalpy, and entropy, at the reference pressure, Pref
|
||||
* of one of the species. The species index is used
|
||||
* to reference into the cp_R, h_RT, and s_R arrays.
|
||||
*
|
||||
* @param temp 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).
|
||||
*/
|
||||
virtual void updatePropertiesTemp(const doublereal temp,
|
||||
doublereal* cp_R,
|
||||
doublereal* h_RT,
|
||||
doublereal* s_R) const = 0;
|
||||
|
||||
//!This utility function reports back the type of
|
||||
//! parameterization and all of the parameters for the
|
||||
//! species, index.
|
||||
/*!
|
||||
* All parameters are output variables
|
||||
*
|
||||
* @param index Species index
|
||||
* @param type Integer type of the standard type
|
||||
* @param minTemp output - Minimum temperature
|
||||
* @param maxTemp output - Maximum temperature
|
||||
* @param refPressure output - reference pressure (Pa).
|
||||
* @param coeffs Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
*/
|
||||
virtual void reportParameters(int &index, int &type,
|
||||
doublereal &minTemp, doublereal &maxTemp,
|
||||
doublereal &refPressure,
|
||||
doublereal* const coeffs) const = 0;
|
||||
|
||||
//! Modify parameters for the standard state
|
||||
/*!
|
||||
* @param coeffs Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
*/
|
||||
virtual void modifyParameters(doublereal* coeffs) {}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
500
Cantera/src/thermo/SpeciesThermoMgr.h
Executable file
500
Cantera/src/thermo/SpeciesThermoMgr.h
Executable file
|
|
@ -0,0 +1,500 @@
|
|||
/**
|
||||
* @file SpeciesThermoMgr.h
|
||||
* This file contains descriptions of templated subclasses of
|
||||
* the virtual base class, SpeciesThermo, which
|
||||
* include SpeciesThermoDuo and SpeciesThermo1
|
||||
* (see \ref spthermo and classes
|
||||
* \link Cantera::SpeciesThermoDuo SpeciesThermoDuo\endlink and
|
||||
* \link Cantera::SpeciesThermo1 SpeciesThermo1\endlink)
|
||||
*
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
// Copyright 2001 California Institute of Technology
|
||||
|
||||
#ifndef CT_SPECIESTHERMO_MGR_H
|
||||
#define CT_SPECIESTHERMO_MGR_H
|
||||
|
||||
#include "ct_defs.h"
|
||||
#include "ctexceptions.h"
|
||||
#include "stringUtils.h"
|
||||
#include "SpeciesThermo.h"
|
||||
#include <map>
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
//! Invokes the 'updateProperties' method of all objects in the list.
|
||||
/*!
|
||||
* This templated function has one template, InputIter. It should
|
||||
* point to a class such as one that inherits from the virtual
|
||||
* base class, SpeciesThermoInterpType, which has
|
||||
* an updateProperties(T, Cp_R, h_RT, s)R) function
|
||||
*
|
||||
* @param begin Beginning iterator
|
||||
* @param end end iterator
|
||||
* @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).
|
||||
*
|
||||
* @ingroup spthermo
|
||||
*/
|
||||
template<class InputIter>
|
||||
inline void _updateAll(InputIter begin,
|
||||
InputIter end,
|
||||
doublereal T,
|
||||
vector_fp& cp_R,
|
||||
vector_fp& h_RT,
|
||||
vector_fp& s_R)
|
||||
{
|
||||
for (; begin != end; ++begin)
|
||||
begin->updateProperties(T, cp_R, h_RT, s_R);
|
||||
}
|
||||
|
||||
//! Iterates through a list of objects which implement a method
|
||||
//! 'minTemp()', and returns the largest 'minTemp' value.
|
||||
/*!
|
||||
* This templated function has one template, InputIter. It should
|
||||
* point to a class such as one that inherits from either
|
||||
* SpeciesThermoInterpType or SpeciesThermo, which have a minTemp() function
|
||||
*
|
||||
* @param begin Beginning iterator
|
||||
* @param end end iterator
|
||||
*
|
||||
* @ingroup spthermo
|
||||
*/
|
||||
template<class InputIter>
|
||||
doublereal _minTemp(InputIter begin, InputIter end) {
|
||||
doublereal _minT = 0.0;
|
||||
for (; begin != end; ++begin)
|
||||
_minT = fmaxx(_minT, begin->minTemp());
|
||||
return _minT;
|
||||
}
|
||||
|
||||
//! Iterates through a list of objects which implement a method
|
||||
//! 'maxTemp()', and returns the smallest 'maxTemp' value.
|
||||
/*!
|
||||
* This templated function has one template, InputIter. It should
|
||||
* point to a class such as one that inherits from either
|
||||
* SpeciesThermoInterpType or SpeciesThermo which have a minTemp() function
|
||||
*
|
||||
* @param begin Beginning iterator
|
||||
* @param end end iterator
|
||||
*
|
||||
* @ingroup spthermo
|
||||
*/
|
||||
template<class _InputIter>
|
||||
doublereal _maxTemp(_InputIter begin, _InputIter end) {
|
||||
doublereal _maxT = 1.e10;
|
||||
for (; begin != end; ++begin)
|
||||
_maxT = fminn(_maxT, begin->maxTemp());
|
||||
return _maxT;
|
||||
}
|
||||
|
||||
/////////////////////// Exceptions //////////////////////////////
|
||||
|
||||
//! Exception thrown if species reference pressures don't match.
|
||||
/*!
|
||||
* @ingroup spthermo
|
||||
*/
|
||||
class RefPressureMismatch : public CanteraError {
|
||||
public:
|
||||
//! constructor
|
||||
/*!
|
||||
* @param proc name of the procecdure
|
||||
* @param prnew reference pressure
|
||||
* @param prold old reference pressure
|
||||
*/
|
||||
RefPressureMismatch(std::string proc, doublereal prnew,
|
||||
doublereal prold) : CanteraError(proc,
|
||||
"Species reference pressure ("
|
||||
+ fp2str(prnew) + ") does not match previously-defined "
|
||||
+ "reference pressure (" + fp2str(prold) + ")") {}
|
||||
//! destructor
|
||||
virtual ~RefPressureMismatch() {}
|
||||
};
|
||||
|
||||
//! Unknown species thermo manager string error
|
||||
/*!
|
||||
* @ingroup spthermo
|
||||
*/
|
||||
class UnknownSpeciesThermo : public CanteraError {
|
||||
public:
|
||||
//! constructor
|
||||
/*!
|
||||
* @param proc name of the procecdure
|
||||
* @param type unknown type
|
||||
*/
|
||||
UnknownSpeciesThermo(std::string proc, int type) :
|
||||
CanteraError(proc, "Specified species parameterization type (" + int2str(type)
|
||||
+ ") does not match any known type.") {}
|
||||
//! destructor
|
||||
virtual ~UnknownSpeciesThermo() {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This species thermo manager requires that all species have one
|
||||
* of two parameterizations.
|
||||
*
|
||||
* Note this seems to be a slow way to do things, and it may be on its way out.
|
||||
*
|
||||
* @ingroup spthermo
|
||||
*/
|
||||
template<class T1, class T2>
|
||||
class SpeciesThermoDuo : public SpeciesThermo {
|
||||
|
||||
public:
|
||||
//! Constructor
|
||||
SpeciesThermoDuo() {}
|
||||
//! Destructor
|
||||
virtual ~SpeciesThermoDuo(){}
|
||||
|
||||
/**
|
||||
* install a new species thermodynamic property
|
||||
* parameterization for one species.
|
||||
*
|
||||
* @param name Name of the species
|
||||
* @param sp The 'update' method will update the property
|
||||
* values for this species
|
||||
* at position i index in the property arrays.
|
||||
* @param type int flag specifying the type of parameterization to be
|
||||
* installed.
|
||||
* @param c vector of coefficients for the parameterization.
|
||||
* This vector is simply passed through to the
|
||||
* parameterization constructor.
|
||||
* @param minTemp minimum temperature for which this parameterization
|
||||
* is valid.
|
||||
* @param maxTemp maximum temperature for which this parameterization
|
||||
* is valid.
|
||||
* @param refPressure standard-state pressure for this
|
||||
* parameterization.
|
||||
* @see speciesThermoTypes.h
|
||||
*/
|
||||
virtual void install(std::string name, int sp, int type,
|
||||
const doublereal* c,
|
||||
doublereal minTemp,
|
||||
doublereal maxTemp,
|
||||
doublereal refPressure) {
|
||||
m_p0 = refPressure;
|
||||
if (type == m_thermo1.ID) {
|
||||
m_thermo1.install(name, sp, 0, c, minTemp, maxTemp,
|
||||
refPressure);
|
||||
speciesToType[sp] = m_thermo1.ID;
|
||||
} else if (type == m_thermo2.ID) {
|
||||
m_thermo2.install(name, sp, 0, c, minTemp, maxTemp,
|
||||
refPressure);
|
||||
speciesToType[sp] = m_thermo2.ID;
|
||||
} else {
|
||||
throw UnknownSpeciesThermo("SpeciesThermoDuo:install",type);
|
||||
}
|
||||
}
|
||||
|
||||
//! Compute the reference-state properties for all species.
|
||||
/*!
|
||||
* Given temperature T in K, this method updates the values of
|
||||
* the non-dimensional heat capacity at constant pressure,
|
||||
* enthalpy, and entropy, at the reference pressure, Pref
|
||||
* of each of the standard states.
|
||||
*
|
||||
* @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).
|
||||
*/
|
||||
virtual void update(doublereal t, doublereal* cp_R,
|
||||
doublereal* h_RT, doublereal* s_R) const {
|
||||
m_thermo1.update(t, cp_R, h_RT, s_R);
|
||||
m_thermo2.update(t, cp_R, h_RT, s_R);
|
||||
}
|
||||
|
||||
//! Minimum temperature.
|
||||
/*!
|
||||
* If no argument is supplied, this
|
||||
* method returns the minimum temperature for which \e all
|
||||
* parameterizations are valid. If an integer index k is
|
||||
* supplied, then the value returned is the minimum
|
||||
* temperature for species k in the phase.
|
||||
*
|
||||
* @param k Species index
|
||||
*/
|
||||
virtual doublereal minTemp(int k = -1) const {
|
||||
doublereal tm1 = m_thermo1.minTemp();
|
||||
doublereal tm2 = m_thermo2.minTemp();
|
||||
return (tm1 < tm2 ? tm2 : tm1);
|
||||
}
|
||||
|
||||
//! Maximum temperature.
|
||||
/*!
|
||||
* If no argument is supplied, this
|
||||
* method returns the maximum temperature for which \e all
|
||||
* parameterizations are valid. If an integer index k is
|
||||
* supplied, then the value returned is the maximum
|
||||
* temperature for parameterization k.
|
||||
*
|
||||
* @param k index for parameterization k
|
||||
*/
|
||||
virtual doublereal maxTemp(int k = -1) const {
|
||||
doublereal tm1 = m_thermo1.maxTemp();
|
||||
doublereal tm2 = m_thermo2.maxTemp();
|
||||
return (tm1 < tm2 ? tm1 : tm2);
|
||||
}
|
||||
|
||||
/**
|
||||
* The reference-state pressure for species k.
|
||||
*
|
||||
* returns the reference state pressure in Pascals for
|
||||
* species k. If k is left out of the argument list,
|
||||
* it returns the reference state pressure for the first
|
||||
* species.
|
||||
* Note that some SpeciesThermo implementations, such
|
||||
* as those for ideal gases, require that all species
|
||||
* in the same phase have the same reference state pressures.
|
||||
*
|
||||
* @param k index for parameterization k
|
||||
*/
|
||||
virtual doublereal refPressure(int k = -1) const {
|
||||
return m_p0;
|
||||
}
|
||||
|
||||
//! This utility function reports the type of parameterization
|
||||
//! used for the species with index number index.
|
||||
/*!
|
||||
*
|
||||
* @param k Species index
|
||||
*/
|
||||
virtual int reportType(int k) const {
|
||||
std::map<int, int>::const_iterator p = speciesToType.find(k);
|
||||
if (p != speciesToType.end()) {
|
||||
const int type = p->second;
|
||||
return type;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*!
|
||||
* This utility function reports back the type of
|
||||
* parameterization and all of the parameters for the
|
||||
* species, index.
|
||||
*
|
||||
* @param index Species index
|
||||
* @param type Integer type of the standard type
|
||||
* @param c Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
* @param minTemp output - Minimum temperature
|
||||
* @param maxTemp output - Maximum temperature
|
||||
* @param refPressure output - reference pressure (Pa).
|
||||
*
|
||||
*/
|
||||
virtual void reportParams(int index, int &type,
|
||||
doublereal * const c,
|
||||
doublereal &minTemp,
|
||||
doublereal &maxTemp,
|
||||
doublereal &refPressure) const {
|
||||
int ctype = reportType(index);
|
||||
if (ctype == m_thermo1.ID) {
|
||||
m_thermo1.reportParams(index, type, c, minTemp, maxTemp,
|
||||
refPressure);
|
||||
} else if (ctype == m_thermo2.ID) {
|
||||
m_thermo2.reportParams(index, type, c, minTemp, maxTemp,
|
||||
refPressure);
|
||||
} else {
|
||||
throw CanteraError(" ", "confused");
|
||||
}
|
||||
}
|
||||
|
||||
//! Modify parameters for the standard state
|
||||
/*!
|
||||
* @param index Species index
|
||||
* @param c Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
*/
|
||||
virtual void modifyParams(int index, doublereal *c) {
|
||||
int ctype = reportType(index);
|
||||
if (ctype == m_thermo1.ID) {
|
||||
m_thermo1.modifyParams(index, c);
|
||||
} else if (ctype == m_thermo2.ID) {
|
||||
m_thermo2.modifyParams(index, c);
|
||||
} else {
|
||||
throw CanteraError("modifyParams", "confused");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
//! Thermo Type 1
|
||||
T1 m_thermo1;
|
||||
//! Thermo Type 2
|
||||
T2 m_thermo2;
|
||||
//! Reference pressure
|
||||
doublereal m_p0;
|
||||
//! map from species to type
|
||||
std::map<int, int> speciesToType;
|
||||
};
|
||||
|
||||
//! This species thermo manager requires that all species have the
|
||||
//! same parameterization.
|
||||
/*!
|
||||
*
|
||||
* This is a templated class. The first template is called SPM. SPM
|
||||
* is an object that calculates the thermo for one species. This
|
||||
* class contains a vector of SPM's, one for each
|
||||
* species. Together, the vector of SPM's is itself a SpeciesThermo
|
||||
* class.
|
||||
*
|
||||
* @todo The form of the template class, SPM, is basically
|
||||
* unspecified. it needs to be nailed down to a specific
|
||||
* form. One way to do this is with a virtual base class
|
||||
* formulation. Note, that the specification could be that it
|
||||
* inherits from the class SpeciesThermo, itself.
|
||||
*
|
||||
* @deprecated Note this is currently unused and it may be on its way out.
|
||||
*
|
||||
* @ingroup spthermo
|
||||
*/
|
||||
template<class SPM>
|
||||
class SpeciesThermo1 : public SpeciesThermo {
|
||||
|
||||
public:
|
||||
//! base constructor
|
||||
SpeciesThermo1() : m_pref(0.0) {}
|
||||
//! destructor
|
||||
virtual ~SpeciesThermo1(){}
|
||||
|
||||
//! Install one species into this Species Thermo Manager
|
||||
/*!
|
||||
* @param name Name of the species
|
||||
* @param sp Species index
|
||||
* @param type species type in terms of an int
|
||||
* @param c Parameters for the species thermo
|
||||
*/
|
||||
virtual void install(std::string name, int sp, int type, const vector_fp& c) {
|
||||
m_thermo.push_back(SPM(sp, c));
|
||||
if (m_pref) {
|
||||
if (m_thermo.begin()->refPressure() != m_pref) {
|
||||
throw RefPressureMismatch("SpeciesThermo1:install",
|
||||
refPressure(), m_pref);
|
||||
}
|
||||
}
|
||||
else m_pref = m_thermo.begin()->refPressure();
|
||||
}
|
||||
|
||||
//! update the object, because the temperature changed
|
||||
/*!
|
||||
* @param t temperature(Kelvin)
|
||||
* @param cp_R vector of dimensionless heat capacity
|
||||
* @param h_RT vector of dimensionless enthalpy
|
||||
* @param s_R vector of dimensionless entropy
|
||||
*/
|
||||
virtual void update(doublereal t, vector_fp& cp_R,
|
||||
vector_fp& h_RT, vector_fp& s_R) const {
|
||||
_updateAll(m_thermo.begin(),m_thermo.end(),
|
||||
t, cp_R, h_RT, s_R);
|
||||
}
|
||||
|
||||
//! update the object for one species, because the temperature changed
|
||||
/*!
|
||||
* @param k species index
|
||||
* @param t temperature(Kelvin)
|
||||
* @param cp_R vector of dimensionless heat capacity
|
||||
* @param h_RT vector of dimensionless enthalpy
|
||||
* @param s_R vector of dimensionless entropy
|
||||
*/
|
||||
virtual void update_one(int k, doublereal t, vector_fp& cp_R,
|
||||
vector_fp& h_RT, vector_fp& s_R) const {
|
||||
m_thermo[k]->update(t, cp_R, h_RT, s_R);
|
||||
}
|
||||
|
||||
//! returns the minimum temperature
|
||||
/*!
|
||||
* @param k species index. Defaults to -1.
|
||||
*/
|
||||
virtual doublereal minTemp(int k = -1) const {
|
||||
if (k < 0)
|
||||
return _minTemp(m_thermo.begin(), m_thermo.end());
|
||||
else
|
||||
return m_thermo[k].minTemp();
|
||||
}
|
||||
|
||||
//! returns the maximum temperature
|
||||
/*!
|
||||
* @param k species index. Defaults to -1.
|
||||
*/
|
||||
virtual doublereal maxTemp(int k = -1) const {
|
||||
if (k < 0)
|
||||
return _maxTemp(m_thermo.begin(), m_thermo.end());
|
||||
else
|
||||
return m_thermo[k].maxTemp();
|
||||
}
|
||||
|
||||
//! returns the reference pressure
|
||||
/*!
|
||||
* @param k species index. Defaults to -1.
|
||||
*/
|
||||
virtual doublereal refPressure(int k = -1) const {
|
||||
return m_pref;
|
||||
}
|
||||
|
||||
//! This utility function reports the type of parameterization
|
||||
//! used for the species with index number index.
|
||||
/*!
|
||||
* Note, all parameterizations are the same, by definition, here
|
||||
*
|
||||
* @param k Species index
|
||||
*/
|
||||
virtual int reportType(int k) const {
|
||||
return m_thermo[k]->reportType(-1);
|
||||
}
|
||||
|
||||
/*!
|
||||
* This utility function reports back the type of
|
||||
* parameterization and all of the parameters for the
|
||||
* species, index.
|
||||
*
|
||||
* @param index Species index
|
||||
* @param type Integer type of the standard type
|
||||
* @param c Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
* @param minTemp output - Minimum temperature
|
||||
* @param maxTemp output - Maximum temperature
|
||||
* @param refPressure output - reference pressure (Pa).
|
||||
*/
|
||||
virtual void reportParams(int index, int &type,
|
||||
doublereal * const c,
|
||||
doublereal &minTemp,
|
||||
doublereal &maxTemp,
|
||||
doublereal &refPressure) const {
|
||||
m_thermo[index]->reportParameters(index, type, c, minTemp, maxTemp, refPressure);
|
||||
}
|
||||
|
||||
//! Modify parameters for the standard state
|
||||
/*!
|
||||
* @param index Species index
|
||||
* @param c Vector of coefficients used to set the
|
||||
* parameters for the standard state.
|
||||
*/
|
||||
virtual void modifyParams(int index, doublereal *c) {
|
||||
m_thermo[index]->modifyParameters(index, c);
|
||||
}
|
||||
|
||||
private:
|
||||
//! Vector of SPM objects. There are m_kk of them
|
||||
std::vector<SPM> m_thermo;
|
||||
//! Reference pressure (Pa)
|
||||
doublereal m_pref;
|
||||
};
|
||||
//#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
227
Cantera/src/thermo/State.cpp
Normal file
227
Cantera/src/thermo/State.cpp
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
/**
|
||||
*
|
||||
* @file State.cpp
|
||||
* Definitions for the class State, that manages the independent variables of temperature, mass density,
|
||||
* and species mass/mole fraction that define the thermodynamic state (see \ref phases and
|
||||
* class \link Cantera::State State\endlink).
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Author$
|
||||
* $Date$
|
||||
* $Revision$
|
||||
*
|
||||
* Copyright 2003-2004 California Institute of Technology
|
||||
* See file License.txt for licensing information
|
||||
*
|
||||
*/
|
||||
|
||||
#include "utilities.h"
|
||||
#include "ctexceptions.h"
|
||||
#include "stringUtils.h"
|
||||
#include "State.h"
|
||||
|
||||
//#ifdef DARWIN
|
||||
//#include <Accelerate.h>
|
||||
//#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
State::State() : m_kk(0), m_temp(0.0), m_dens(0.001), m_mmw(0.0) {}
|
||||
|
||||
State::~State() {}
|
||||
|
||||
State::State(const State& right) :
|
||||
m_kk(0),
|
||||
m_temp(0.0),
|
||||
m_dens(0.001),
|
||||
m_mmw(0.0) {
|
||||
/*
|
||||
* Call the assignment operator.
|
||||
*/
|
||||
*this = operator=(right);
|
||||
}
|
||||
|
||||
/*
|
||||
* Assignment operator for the State Class
|
||||
*/
|
||||
State& State::operator=(const State& right) {
|
||||
/*
|
||||
* Check for self assignment.
|
||||
*/
|
||||
if (this == &right) return *this;
|
||||
/*
|
||||
* We do a straight assignment operator on all of the
|
||||
* data. The vectors are copied.
|
||||
*/
|
||||
m_temp = right.m_temp;
|
||||
m_dens = right.m_dens;
|
||||
m_mmw = right.m_mmw;
|
||||
m_y = right.m_y;
|
||||
m_molwts = right.m_molwts;
|
||||
m_rmolwts = right.m_rmolwts;
|
||||
/*
|
||||
* Return the reference to the current object
|
||||
*/
|
||||
return *this;
|
||||
}
|
||||
|
||||
doublereal State::moleFraction(int k) const {
|
||||
if (k >= 0 && k < m_kk) {
|
||||
return m_ym[k] * m_mmw;
|
||||
}
|
||||
else {
|
||||
throw CanteraError("State:moleFraction",
|
||||
"illegal species index number");
|
||||
}
|
||||
}
|
||||
|
||||
void State::setMoleFractions(const doublereal* x) {
|
||||
int k;
|
||||
doublereal sum = 0.0, norm = 0.0;
|
||||
sum = dot(x, x + m_kk, m_molwts.begin());
|
||||
for (k = 0; k != m_kk; ++k) {
|
||||
m_ym[k] = x[k] / sum;
|
||||
m_y[k] = m_molwts[k]*m_ym[k];
|
||||
norm += x[k];
|
||||
}
|
||||
m_mmw = sum/norm;
|
||||
}
|
||||
|
||||
void State::setMoleFractions_NoNorm(const doublereal* x) {
|
||||
int k;
|
||||
m_mmw = dot(x, x + m_kk, m_molwts.begin());
|
||||
doublereal rmmw = 1.0/m_mmw;
|
||||
for (k = 0; k != m_kk; ++k) {
|
||||
m_ym[k] = x[k]*rmmw;
|
||||
m_y[k] = m_ym[k] * m_molwts[k];
|
||||
}
|
||||
}
|
||||
|
||||
doublereal State::massFraction(int k) const {
|
||||
if (k >= 0 && k < m_kk) {
|
||||
return m_y[k];
|
||||
}
|
||||
else {
|
||||
throw CanteraError("State:massFraction",
|
||||
"illegal species index number");
|
||||
}
|
||||
}
|
||||
|
||||
doublereal State::concentration(int k) const {
|
||||
if (k >= 0 && k < m_kk) {
|
||||
return m_y[k] * m_dens * m_rmolwts[k] ;
|
||||
}
|
||||
else {
|
||||
throw CanteraError("State:massFraction",
|
||||
"illegal species index number");
|
||||
}
|
||||
}
|
||||
|
||||
void State::setMassFractions(const doublereal* y) {
|
||||
doublereal norm = 0.0, sum = 0.0;
|
||||
int k;
|
||||
//cblas_dcopy(m_kk, y, 1, m_y.begin(), 1);
|
||||
for (k = 0; k != m_kk; ++k) {
|
||||
norm += y[k];
|
||||
m_y[k] = y[k];
|
||||
}
|
||||
//scale(y, y + m_kk, m_y.begin(), 1.0/norm);
|
||||
scale(m_kk, 1.0/norm, m_y.begin());
|
||||
|
||||
for (k = 0; k != m_kk; ++k) {
|
||||
m_ym[k] = m_y[k] * m_rmolwts[k];
|
||||
sum += m_ym[k];
|
||||
}
|
||||
m_mmw = 1.0/sum;
|
||||
}
|
||||
|
||||
void State::setMassFractions_NoNorm(const doublereal* y) {
|
||||
int k;
|
||||
doublereal sum = 0.0;
|
||||
for (k = 0; k != m_kk; ++k) {
|
||||
m_y[k] = y[k];
|
||||
m_ym[k] = m_y[k] * m_rmolwts[k];
|
||||
sum += m_ym[k];
|
||||
}
|
||||
m_mmw = 1.0/sum;
|
||||
}
|
||||
|
||||
doublereal State::sum_xlogx() const {
|
||||
return m_mmw* Cantera::sum_xlogx(m_ym.begin(), m_ym.end()) + log(m_mmw);
|
||||
}
|
||||
|
||||
doublereal State::sum_xlogQ(doublereal* Q) const {
|
||||
return m_mmw * Cantera::sum_xlogQ(m_ym.begin(), m_ym.end(), Q);
|
||||
}
|
||||
|
||||
void State::setConcentrations(const doublereal* c) {
|
||||
int k;
|
||||
doublereal sum = 0.0, norm = 0.0;
|
||||
for (k = 0; k != m_kk; ++k) {
|
||||
sum += c[k]*m_molwts[k];
|
||||
norm += c[k];
|
||||
}
|
||||
m_mmw = sum/norm;
|
||||
setDensity(sum);
|
||||
doublereal rsum = 1.0/sum;
|
||||
for (k = 0; k != m_kk; ++k) {
|
||||
m_ym[k] = c[k] * rsum;
|
||||
m_y[k] = m_ym[k] * m_molwts[k];
|
||||
}
|
||||
}
|
||||
|
||||
void State::getConcentrations(doublereal* c) const {
|
||||
scale(m_ym.begin(), m_ym.end(), c, m_dens);
|
||||
}
|
||||
|
||||
doublereal State::mean_Y(const doublereal* Q) const {
|
||||
return dot(m_y.begin(), m_y.end(), Q);
|
||||
}
|
||||
|
||||
void State::getMoleFractions(doublereal* x) const {
|
||||
scale(m_ym.begin(), m_ym.end(), x, m_mmw);
|
||||
}
|
||||
|
||||
void State::getMassFractions(doublereal* y) const {
|
||||
copy(m_y.begin(), m_y.end(), y);
|
||||
}
|
||||
|
||||
void State::init(const array_fp& mw) {
|
||||
m_kk = mw.size();
|
||||
m_molwts.resize(m_kk);
|
||||
m_rmolwts.resize(m_kk);
|
||||
m_y.resize(m_kk, 0.0);
|
||||
m_ym.resize(m_kk, 0.0);
|
||||
copy(mw.begin(), mw.end(), m_molwts.begin());
|
||||
for (int k = 0; k < m_kk; k++) {
|
||||
if (m_molwts[k] < 0.0) {
|
||||
throw CanteraError("State::init",
|
||||
"negative molecular weight for species number "+int2str(k));
|
||||
}
|
||||
/*
|
||||
* Some surface phases may define species representing
|
||||
* empty sites that have zero molecular weight. Give them
|
||||
* a very small molecular weight to avoid dividing by
|
||||
* zero.
|
||||
*/
|
||||
if (m_molwts[k] < Tiny) m_molwts[k] = Tiny;
|
||||
m_rmolwts[k] = 1.0/m_molwts[k];
|
||||
}
|
||||
|
||||
/*
|
||||
* Now that we have resized the State object, let's fill it with
|
||||
* a valid mass fraction vector that sums to one. The State object
|
||||
* should never have a mass fraction vector that doesn't sum to one.
|
||||
* We will assume that species 0 has a mass fraction of 1.0 and
|
||||
* mass fraction of all other species is 0.0.
|
||||
*/
|
||||
m_y[0] = 1.0;
|
||||
m_ym[0] = m_y[0] * m_rmolwts[0];
|
||||
m_mmw = 1.0 / m_ym[0];
|
||||
}
|
||||
|
||||
}
|
||||
415
Cantera/src/thermo/State.h
Executable file
415
Cantera/src/thermo/State.h
Executable file
|
|
@ -0,0 +1,415 @@
|
|||
/**
|
||||
* @file State.h
|
||||
* Header for the class State, that manages the independent variables of temperature, mass density,
|
||||
* and species mass/mole fraction that define the thermodynamic state (see \ref phases and
|
||||
* class \link Cantera::State State\endlink).
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Author$
|
||||
* $Date$
|
||||
* $Revision$
|
||||
*
|
||||
* Copyright 2001-2003 California Institute of Technology
|
||||
* See file License.txt for licensing information
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CT_STATE2_H
|
||||
#define CT_STATE2_H
|
||||
|
||||
#include "ct_defs.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
|
||||
//! Manages the independent variables of temperature, mass density,
|
||||
//! and species mass/mole fraction that define the thermodynamic
|
||||
//! state.
|
||||
/*!
|
||||
* Class State stores just enough information about a
|
||||
* multicomponent solution to specify its intensive thermodynamic
|
||||
* state. It stores values for the temperature, mass density, and
|
||||
* an array of species mass fractions. It also stores an array of
|
||||
* species molecular weights, which are used to convert between
|
||||
* mole and mass representations of the composition. These are the
|
||||
* \e only properties of the species that class State knows about.
|
||||
* For efficiency in mass/mole conversion, the vector of mass
|
||||
* fractions divided by molecular weight \f$ Y_k/M_k \f$ is also
|
||||
* stored.
|
||||
*
|
||||
* Class State is not usually used directly in application
|
||||
* programs. Its primary use is as a base class for class
|
||||
* Phase. Class State has no virtual methods, and none of its
|
||||
* methods are meant to be overloaded. However, this is one exception.
|
||||
* If the phase is incompressible, then the density must be replaced
|
||||
* by the pressure as the independent variable. In this case, functions
|
||||
* such as setMassFraction within the class %State must actually now
|
||||
* calculate the density (at constant T and P) instead of leaving
|
||||
* it alone as befits an independent variable. Threfore, these type
|
||||
* of functions are virtual functions and need to be overloaded
|
||||
* for incompressible phases. Note, for almost incompressible phases
|
||||
* (or phases which utilize standard states based on a T and P) this
|
||||
* may be advantageous as well, and they need to overload these functions
|
||||
* too.
|
||||
*
|
||||
* @ingroup phases
|
||||
*/
|
||||
class State {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
State();
|
||||
|
||||
/**
|
||||
* Destructor. Since no memory is allocated by methods of this
|
||||
* class, the destructor does nothing.
|
||||
*/
|
||||
virtual ~State();
|
||||
|
||||
/**
|
||||
* Copy Constructor for the State Class
|
||||
*
|
||||
* @param right Reference to the class to be copied.
|
||||
*/
|
||||
State(const State& right);
|
||||
|
||||
/**
|
||||
* Assignment operator for the state class.
|
||||
*
|
||||
* @param right Reference to the class to be copied.
|
||||
*/
|
||||
State& operator=(const State& right);
|
||||
|
||||
|
||||
/// @name Species Information
|
||||
///
|
||||
/// The only thing class State knows about the species is their
|
||||
/// molecular weights.
|
||||
//@{
|
||||
|
||||
/// Return a read-only reference to the array of molecular
|
||||
/// weights.
|
||||
const array_fp& molecularWeights() const { return m_molwts; }
|
||||
|
||||
|
||||
//@}
|
||||
/// @name Composition
|
||||
//@{
|
||||
|
||||
|
||||
//! Get the species mole fraction vector.
|
||||
/*!
|
||||
* @param x On return, x contains the mole fractions. Must have a
|
||||
* length greater than or equal to the number of species.
|
||||
*/
|
||||
void getMoleFractions(doublereal* x) const;
|
||||
|
||||
|
||||
//! The mole fraction of species k.
|
||||
/*!
|
||||
* If k is ouside the valid
|
||||
* range, an exception will be thrown. Note that it is
|
||||
* somewhat more efficent to call getMoleFractions if the
|
||||
* mole fractions of all species are desired.
|
||||
* @param k species index
|
||||
*/
|
||||
doublereal moleFraction(int k) const;
|
||||
|
||||
/**
|
||||
* Set the mole fractions to the specified values, and then
|
||||
* normalize them so that they sum to 1.0.
|
||||
* @param x Array of unnormalized mole fraction values (input).
|
||||
* Must have a length greater than or equal to the number of
|
||||
* species.
|
||||
*
|
||||
* @param x Input vector of mole fractions.
|
||||
* Length is m_kk.
|
||||
*/
|
||||
virtual void setMoleFractions(const doublereal* x);
|
||||
|
||||
/**
|
||||
* Set the mole fractions to the specified values without
|
||||
* normalizing. This is useful when the normalization
|
||||
* condition is being handled by some other means, for example
|
||||
* by a constraint equation as part of a larger set of
|
||||
* equations.
|
||||
*
|
||||
* @param x Input vector of mole fractions.
|
||||
* Length is m_kk.
|
||||
*/
|
||||
virtual void setMoleFractions_NoNorm(const doublereal* x);
|
||||
|
||||
/**
|
||||
* Get the species mass fractions.
|
||||
* @param y On return, y
|
||||
* contains the mass fractions. Array \a y must have a length
|
||||
* greater than or equal to the number of species.
|
||||
*
|
||||
* @param y Output vector of mass fractions.
|
||||
* Length is m_kk.
|
||||
*/
|
||||
void getMassFractions(doublereal* y) const;
|
||||
|
||||
//! Mass fraction of species k.
|
||||
/*!
|
||||
* If k is outside the valid
|
||||
* range, an exception will be thrown. Note that it is
|
||||
* somewhat more efficent to call getMassFractions if the
|
||||
* mass fractions of all species are desired.
|
||||
*
|
||||
* @param k species index
|
||||
*/
|
||||
doublereal massFraction(int k) const;
|
||||
|
||||
/**
|
||||
* Set the mass fractions to the specified values, and then
|
||||
* normalize them so that they sum to 1.0.
|
||||
* @param y Array of unnormalized mass fraction values (input).
|
||||
* Must have a length greater than or equal to the number of
|
||||
* species.
|
||||
*
|
||||
* @param y Input vector of mass fractions.
|
||||
* Length is m_kk.
|
||||
*/
|
||||
virtual void setMassFractions(const doublereal* y);
|
||||
|
||||
/**
|
||||
* Set the mass fractions to the specified values without
|
||||
* normalizing. This is useful when the normalization
|
||||
* condition is being handled by some other means, for example
|
||||
* by a constraint equation as part of a larger set of
|
||||
* equations.
|
||||
*
|
||||
* @param y Input vector of mass fractions.
|
||||
* Length is m_kk.
|
||||
*/
|
||||
virtual void setMassFractions_NoNorm(const doublereal* y);
|
||||
|
||||
/**
|
||||
* Get the species concentrations (kmol/m^3). @param c On
|
||||
* return, \a c contains the concentrations for all species.
|
||||
* Array \a c must have a length greater than or equal to the
|
||||
* number of species.
|
||||
*/
|
||||
void getConcentrations(doublereal* c) const;
|
||||
|
||||
/**
|
||||
* Concentration of species k. If k is outside the valid
|
||||
* range, an exception will be thrown.
|
||||
*
|
||||
* @param k Index of species
|
||||
*/
|
||||
doublereal concentration(int k) const;
|
||||
|
||||
/**
|
||||
* Set the concentrations to the specified values within the
|
||||
* phase.
|
||||
*
|
||||
* @param c The input vector to this routine is in dimensional
|
||||
* units. For volumetric phases c[k] is the
|
||||
* concentration of the kth species in kmol/m3.
|
||||
* For surface phases, c[k] is the concentration
|
||||
* in kmol/m2. The length of the vector is the number
|
||||
* of species in the phase.
|
||||
*/
|
||||
virtual void setConcentrations(const doublereal* c);
|
||||
|
||||
/**
|
||||
* Returns a read-only pointer to the start of the
|
||||
* massFraction array
|
||||
*/
|
||||
const doublereal* massFractions() const { return &m_y[0]; }
|
||||
|
||||
/**
|
||||
* Returns a read-only pointer to the start of the
|
||||
* moleFraction/MW array. This array is the array of mole
|
||||
* fractions, each divided by the mean molecular weight.
|
||||
*/
|
||||
const doublereal* moleFractdivMMW() const { return &m_ym[0];}
|
||||
|
||||
|
||||
//@}
|
||||
|
||||
/// @name Mean Properties
|
||||
//@{
|
||||
/**
|
||||
* Evaluate the mole-fraction-weighted mean of Q:
|
||||
* \f[ \sum_k X_k Q_k. \f]
|
||||
* Array Q should contain pure-species molar property
|
||||
* values.
|
||||
*
|
||||
* @param Q input vector of length m_kk that is to be averaged.
|
||||
* @return
|
||||
* mole-freaction-weighted mean of Q
|
||||
*/
|
||||
doublereal mean_X(const doublereal* Q) const {
|
||||
return m_mmw*std::inner_product(m_ym.begin(), m_ym.end(), Q, 0.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the mass-fraction-weighted mean of Q:
|
||||
* \f[ \sum_k Y_k Q_k \f]
|
||||
*
|
||||
* @param Q Array Q contains a vector of species property values in mass units.
|
||||
* @return
|
||||
* Return value containing the mass-fraction-weighted mean of Q.
|
||||
*/
|
||||
doublereal mean_Y(const doublereal* Q) const;
|
||||
|
||||
/**
|
||||
* The mean molecular weight. Units: (kg/kmol)
|
||||
*/
|
||||
doublereal meanMolecularWeight() const {
|
||||
return m_mmw;
|
||||
}
|
||||
|
||||
//! Evaluate \f$ \sum_k X_k \log X_k \f$.
|
||||
/*!
|
||||
* @return
|
||||
* returns the indicated sum. units are dimensionless.
|
||||
*/
|
||||
doublereal sum_xlogx() const;
|
||||
|
||||
//! Evaluate \f$ \sum_k X_k \log Q_k \f$.
|
||||
/*!
|
||||
* @param Q Vector of length m_kk to take the log average of
|
||||
* @return Returns the indicated sum.
|
||||
*/
|
||||
doublereal sum_xlogQ(doublereal* Q) const;
|
||||
//@}
|
||||
|
||||
/// @name Thermodynamic Properties
|
||||
/// Class State only stores enough thermodynamic data to
|
||||
/// specify the state. In addition to composition information,
|
||||
/// it stores the temperature and
|
||||
/// mass density.
|
||||
//@{
|
||||
|
||||
/// Temperature (K).
|
||||
doublereal temperature() const { return m_temp; }
|
||||
|
||||
/// Density (kg/m^3).
|
||||
doublereal density() const { return m_dens; }
|
||||
|
||||
/// Molar density (kmol/m^3).
|
||||
doublereal molarDensity() const {
|
||||
return m_dens/meanMolecularWeight();
|
||||
}
|
||||
|
||||
//! Set the internally storred density (kg/m^3) of the phase
|
||||
/*!
|
||||
* Note the density of a phase is an indepedent variable.
|
||||
*
|
||||
* @param density Input density (kg/m^3).
|
||||
*/
|
||||
virtual void setDensity(doublereal density) {
|
||||
m_dens = density;
|
||||
}
|
||||
|
||||
//! Set the internally storred molar density (kmol/m^3) of the phase.
|
||||
/*!
|
||||
* @param molarDensity Input molar density (kmol/m^3).
|
||||
*/
|
||||
virtual void setMolarDensity(doublereal molarDensity) {
|
||||
m_dens = molarDensity*meanMolecularWeight();
|
||||
}
|
||||
|
||||
//! Set the temperature (K).
|
||||
/*!
|
||||
* This function sets the internally storred temperature of the phase.
|
||||
*
|
||||
* @param temp Temperature in kelvin
|
||||
*
|
||||
* @todo Make State::setTemperature a virtual function
|
||||
*/
|
||||
void setTemperature(doublereal temp) {
|
||||
m_temp = temp;
|
||||
}
|
||||
//@}
|
||||
|
||||
//! True if the number species has been set
|
||||
bool ready() const { return (m_kk > 0); }
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Initialize. Make a local copy of the vector of
|
||||
* molecular weights, and resize the composition arrays to
|
||||
* the appropriate size. The only information an instance of
|
||||
* State has about the species is their molecular weights.
|
||||
*
|
||||
* @param mw Vector of molecular weights of the species.
|
||||
*/
|
||||
void init(const array_fp& mw); //, density_is_independent = true);
|
||||
|
||||
/**
|
||||
* m_kk is the number of species in the phase
|
||||
*/
|
||||
int m_kk;
|
||||
|
||||
//! Set the molecular weight of a single species to a given value
|
||||
/*!
|
||||
* @param k id of the species
|
||||
* @param mw Molecular Weight (kg kmol-1)
|
||||
*/
|
||||
void setMolecularWeight(int k, double mw) {
|
||||
m_molwts[k] = mw;
|
||||
m_rmolwts[k] = 1.0/mw;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Temperature. This is an independent variable
|
||||
* units = Kelvin
|
||||
*/
|
||||
doublereal m_temp;
|
||||
|
||||
/**
|
||||
* Density. This is an independent variable except in
|
||||
* the incompressible degenerate case. Thus,
|
||||
* the pressure is determined from this variable
|
||||
* not the other way round.
|
||||
* units = kg m-3
|
||||
*/
|
||||
doublereal m_dens;
|
||||
|
||||
/**
|
||||
* m_mmw is the mean molecular weight of the mixture
|
||||
* (kg kmol-1)
|
||||
*/
|
||||
doublereal m_mmw;
|
||||
|
||||
/**
|
||||
* m_ym[k] = mole fraction of species k divided by the
|
||||
* mean molecular weight of mixture.
|
||||
*/
|
||||
mutable array_fp m_ym;
|
||||
|
||||
/**
|
||||
* m_y[k] = mass fraction of species k
|
||||
*/
|
||||
mutable array_fp m_y;
|
||||
|
||||
/**
|
||||
* m_molwts[k] = molecular weight of species k (kg kmol-1)
|
||||
*/
|
||||
array_fp m_molwts;
|
||||
|
||||
/**
|
||||
* m_rmolwts[k] = inverse of the molecular weight of species k
|
||||
* units = kmol kg-1.
|
||||
*/
|
||||
array_fp m_rmolwts;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
74
Cantera/src/thermo/StoichSubstance.cpp
Normal file
74
Cantera/src/thermo/StoichSubstance.cpp
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
*
|
||||
* @file StoichSubstance.cpp
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma warning(disable:4786)
|
||||
#pragma warning(disable:4503)
|
||||
#endif
|
||||
|
||||
#include "ct_defs.h"
|
||||
#include "mix_defs.h"
|
||||
#include "StoichSubstance.h"
|
||||
#include "SpeciesThermo.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
void StoichSubstance::initThermo() {
|
||||
m_kk = nSpecies();
|
||||
if (m_kk > 1) {
|
||||
throw CanteraError("initThermo",
|
||||
"stoichiometric substances may only contain one species.");
|
||||
}
|
||||
doublereal tmin = m_spthermo->minTemp();
|
||||
doublereal tmax = m_spthermo->maxTemp();
|
||||
if (tmin > 0.0) m_tmin = tmin;
|
||||
if (tmax > 0.0) m_tmax = tmax;
|
||||
m_p0 = refPressure();
|
||||
|
||||
int leng = m_kk;
|
||||
m_h0_RT.resize(leng);
|
||||
m_cp0_R.resize(leng);
|
||||
m_s0_R.resize(leng);
|
||||
}
|
||||
|
||||
|
||||
void StoichSubstance::_updateThermo() const {
|
||||
doublereal tnow = temperature();
|
||||
if (m_tlast != tnow) {
|
||||
m_spthermo->update(tnow, &m_cp0_R[0], &m_h0_RT[0],
|
||||
&m_s0_R[0]);
|
||||
m_tlast = tnow;
|
||||
}
|
||||
}
|
||||
|
||||
void StoichSubstance::
|
||||
getUnitsStandardConc(double *uA, int k, int sizeUA) {
|
||||
for (int i = 0; i < sizeUA; i++) {
|
||||
uA[i] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
void StoichSubstance::setParameters(int n, double * c) {
|
||||
double rho = c[0];
|
||||
setDensity(rho);
|
||||
}
|
||||
|
||||
void StoichSubstance::getParameters(int &n, double * const c) {
|
||||
double rho = density();
|
||||
c[0] = rho;
|
||||
}
|
||||
|
||||
void StoichSubstance::setParametersFromXML(const XML_Node& eosdata) {
|
||||
eosdata._require("model","StoichSubstance");
|
||||
doublereal rho = getFloat(eosdata, "density", "-");
|
||||
setDensity(rho);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
429
Cantera/src/thermo/StoichSubstance.h
Normal file
429
Cantera/src/thermo/StoichSubstance.h
Normal file
|
|
@ -0,0 +1,429 @@
|
|||
/**
|
||||
*
|
||||
* @file StoichSubstance.h
|
||||
*
|
||||
* This file contains the class declarations for the StoichSubstance
|
||||
* ThermoPhase class.
|
||||
*/
|
||||
|
||||
/* $Author$
|
||||
* $Date$
|
||||
* $Revision$
|
||||
*
|
||||
* Copyright 2001 California Institute of Technology
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CT_STOICHSUBSTANCE_H
|
||||
#define CT_STOICHSUBSTANCE_H
|
||||
|
||||
#include "mix_defs.h"
|
||||
#include "ThermoPhase.h"
|
||||
#include "SpeciesThermo.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
/**
|
||||
* @ingroup thermoprops
|
||||
*
|
||||
* Class StoichSubstance represents a stoichiometric (fixed composition)
|
||||
* incompressible substance.
|
||||
* \nosubgrouping
|
||||
*
|
||||
*/
|
||||
class StoichSubstance : public ThermoPhase {
|
||||
|
||||
public:
|
||||
|
||||
StoichSubstance():
|
||||
m_kk(0),
|
||||
m_tmin(0.0),
|
||||
m_tmax(0.0),
|
||||
m_press(OneAtm),
|
||||
m_p0(OneAtm),
|
||||
m_tlast(-1.0) {}
|
||||
|
||||
virtual ~StoichSubstance() {}
|
||||
|
||||
/**
|
||||
*
|
||||
* @name Utilities
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Equation of state flag. Returns the value cStoichSubstance,
|
||||
* defined in mix_defs.h.
|
||||
*/
|
||||
virtual int eosType() const { return cStoichSubstance; }
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @name Molar Thermodynamic Properties of the Solution ---------
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Molar enthalpy. Units: J/kmol. For an incompressible,
|
||||
* stoichiometric substance, the internal energy is
|
||||
* independent of pressure, and therefore the molar enthalpy
|
||||
* is \f[ \hat h(T, P) = \hat u(T) + P \hat v \f], where the
|
||||
* molar specific volume is constant.
|
||||
*/
|
||||
virtual doublereal enthalpy_mole() const {
|
||||
double hh = intEnergy_mole() + m_press / molarDensity();
|
||||
return hh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Molar internal energy. J/kmol. 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.
|
||||
*/
|
||||
virtual doublereal intEnergy_mole() const {
|
||||
_updateThermo();
|
||||
return GasConstant * temperature() * m_h0_RT[0]
|
||||
- m_p0 / molarDensity();
|
||||
}
|
||||
|
||||
/**
|
||||
* Molar entropy. Units: J/kmol/K. For an incompressible,
|
||||
* stoichiometric substance, the molar entropy depends only on
|
||||
* the temperature.
|
||||
*/
|
||||
virtual doublereal entropy_mole() const {
|
||||
_updateThermo();
|
||||
return GasConstant * m_s0_R[0];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Molar gibbs Function. Units: J/kmol. This is determined
|
||||
* from the molar enthalpy and entropy functions.
|
||||
*/
|
||||
virtual doublereal gibbs_mole() const {
|
||||
return enthalpy_mole() - temperature() * entropy_mole();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Molar heat capacity at constant pressure. Units: J/kmol/K.
|
||||
* For an incompressible substance, \f$ \hat c_p = \hat c_v\f$.
|
||||
*/
|
||||
virtual doublereal cp_mole() const {
|
||||
_updateThermo();
|
||||
return GasConstant * m_cp0_R[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Molar heat capacity at constant volume. Units: J/kmol/K.
|
||||
* For an incompressible substance, \f$ \hat c_p = \hat c_v\f$.
|
||||
*/
|
||||
virtual doublereal cv_mole() const {
|
||||
return cp_mole();
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
|
||||
/**
|
||||
* @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 storred
|
||||
* pressure value.
|
||||
*/
|
||||
virtual doublereal pressure() const {
|
||||
return m_press;
|
||||
}
|
||||
|
||||
|
||||
//! 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) {
|
||||
m_press = p;
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
/**
|
||||
* @name Chemical Potentials and Activities
|
||||
*@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* This method returns the array of generalized
|
||||
* concentrations. For a stoichiometric substance, there is
|
||||
* only one species, and the generalized concentration is 1.0.
|
||||
*/
|
||||
virtual void getActivityConcentrations(doublereal* c) const {
|
||||
c[0] = 1.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The standard concentration. This is defined as the concentration
|
||||
* by which the generalized concentration is normalized to produce
|
||||
* the activity.
|
||||
*/
|
||||
virtual doublereal standardConcentration(int k=0) const {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the natural logarithm of the standard
|
||||
* concentration of the kth species
|
||||
*/
|
||||
virtual doublereal logStandardConc(int k=0) const {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array of chemical potentials at unit activity
|
||||
* \f$ \mu^0_k \f$.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
virtual void getStandardChemPotentials(doublereal* mu0) const {
|
||||
mu0[0] = gibbs_mole();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the units of the standard and generalized
|
||||
* concentrations Note they have the same units, as their
|
||||
* ratio is defined to be equal to the activity of the kth
|
||||
* species in the solution, which is unitless.
|
||||
*
|
||||
* This routine is used in print out applications where the
|
||||
* units are needed. Usually, MKS units are assumed throughout
|
||||
* the program and in the XML input files.
|
||||
*
|
||||
* uA[0] = kmol units - default = 0
|
||||
* uA[1] = m units - default = 0
|
||||
* uA[2] = kg units - default = 0;
|
||||
* uA[3] = Pa(pressure) units - default = 0;
|
||||
* uA[4] = Temperature units - default = 0;
|
||||
* uA[5] = time units - default = 0
|
||||
*/
|
||||
virtual void getUnitsStandardConc(double *uA, int k = 0,
|
||||
int sizeUA = 6);
|
||||
|
||||
|
||||
//@}
|
||||
/// @name Partial Molar Properties of the Solution ----------------------------------
|
||||
//@{
|
||||
|
||||
|
||||
/**
|
||||
* Get the array of non-dimensional chemical potentials
|
||||
* \f$ \mu_k / \hat R T \f$.
|
||||
*/
|
||||
virtual void getChemPotentials_RT(doublereal* mu) const {
|
||||
mu[0] = gibbs_mole() / (GasConstant * temperature());
|
||||
}
|
||||
|
||||
/**
|
||||
* For a stoichiometric substance, there is only one species.
|
||||
* This method returns the molar gibbs function in the
|
||||
* first element of array \c mu.
|
||||
*/
|
||||
virtual void getChemPotentials(doublereal* mu) const {
|
||||
mu[0] = gibbs_mole();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the species electrochemical potentials. Units: J/kmol.
|
||||
* This method adds a term \f$ Fz_k \phi_k \f$ to the
|
||||
* to each chemical potential.
|
||||
*/
|
||||
void getElectrochemPotentials(doublereal* mu) const {
|
||||
getChemPotentials(mu);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of partial molar enthalpies for the species
|
||||
* in the mixture.
|
||||
* Units (J/kmol)
|
||||
*/
|
||||
virtual void getPartialMolarEnthalpies(doublereal* hbar) const {
|
||||
hbar[0] = enthalpy_mole();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of partial molar entropies of the species in the
|
||||
* solution. Units: J/kmol/K.
|
||||
*/
|
||||
virtual void getPartialMolarEntropies(doublereal* sbar) const {
|
||||
sbar[0] = entropy_mole();
|
||||
}
|
||||
|
||||
/**
|
||||
* returns an array of partial molar volumes of the species
|
||||
* in the solution. Units: m^3 kmol-1.
|
||||
*/
|
||||
virtual void getPartialMolarVolumes(doublereal* vbar) const {
|
||||
vbar[0] = 1.0 / molarDensity();
|
||||
}
|
||||
|
||||
|
||||
//@}
|
||||
/// @name Properties of the Standard State of the Species in the Solution -------------------------------------
|
||||
//@{
|
||||
/**
|
||||
* Get the nondimensional Enthalpy functions for the species
|
||||
* at their standard states at the current
|
||||
* <I>T</I> and <I>P</I> of the solution.
|
||||
*/
|
||||
virtual void getEnthalpy_RT(doublereal* hrt) const {
|
||||
hrt[0] = enthalpy_mole() / (GasConstant * temperature());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the array of nondimensional Enthalpy functions for the
|
||||
* standard state species
|
||||
* at the current <I>T</I> and <I>P</I> of the solution.
|
||||
*/
|
||||
virtual void getEntropy_R(doublereal* sr) const {
|
||||
sr[0] = entropy_mole() / GasConstant;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the nondimensional Gibbs functions for the species
|
||||
* at their standard states of solution at the current T and P
|
||||
* of the solution.
|
||||
*/
|
||||
virtual void getGibbs_RT(doublereal* grt) const {
|
||||
grt[0] = gibbs_mole() / (GasConstant * temperature());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the nondimensional Heat Capacities at constant
|
||||
* pressure for the standard state of the species
|
||||
* at the current T and P.
|
||||
*/
|
||||
virtual void getCp_R(doublereal* cpr) const {
|
||||
cpr[0] = cp_mole() / GasConstant;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the standard volumes for the standard state of the species
|
||||
* at the current T and P
|
||||
*/
|
||||
virtual void getStandardVolumes(doublereal*vol) const {
|
||||
vol[0] = 1.0 / molarDensity();
|
||||
}
|
||||
|
||||
//@}
|
||||
/// @name Thermodynamic Values for the Species Reference States --------------------
|
||||
//@{
|
||||
|
||||
/**
|
||||
* Returns the vector of nondimensional
|
||||
* enthalpies of the reference state at the current temperature
|
||||
* of the solution and the reference pressure for the species.
|
||||
*
|
||||
* This function fills in its one entry in hrt[] by calling
|
||||
* the underlying species thermo function for the
|
||||
* dimensionless enthalpy.
|
||||
*/
|
||||
virtual void getEnthalpy_RT_ref(doublereal *hrt) const {
|
||||
_updateThermo();
|
||||
hrt[0] = m_h0_RT[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the vector of nondimensional
|
||||
* enthalpies of the reference state at the current temperature
|
||||
* of the solution and the reference pressure for the species.
|
||||
*
|
||||
* This function fills in its one entry in hrt[] by calling
|
||||
* the underlying species thermo function for the
|
||||
* dimensionless gibbs free energy, calculated from the
|
||||
* dimensionless enthalpy and entropy.
|
||||
*/
|
||||
virtual void getGibbs_RT_ref(doublereal *grt) const {
|
||||
_updateThermo();
|
||||
grt[0] = m_h0_RT[0] - m_s0_R[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the vector of the
|
||||
* gibbs function of the reference state at the current temperature
|
||||
* of the solution and the reference pressure for the species.
|
||||
* units = J/kmol
|
||||
*
|
||||
* This function fills in its one entry in g[] by calling
|
||||
* the underlying species thermo functions for the
|
||||
* gibbs free energy, calculated from enthalpy and the
|
||||
* entropy, and the multiplying by RT.
|
||||
*/
|
||||
virtual void getGibbs_ref(doublereal *g) const {
|
||||
getGibbs_RT_ref(g);
|
||||
g[0] *= GasConstant * temperature();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the vector of nondimensional
|
||||
* entropies of the reference state at the current temperature
|
||||
* of the solution and the reference pressure for the species.
|
||||
*
|
||||
* This function fills in its one entry in hrt[] by calling
|
||||
* the underlying species thermo function for the
|
||||
* dimensionless entropy.
|
||||
*/
|
||||
virtual void getEntropy_R_ref(doublereal *er) const {
|
||||
_updateThermo();
|
||||
er[0] = m_s0_R[0];
|
||||
}
|
||||
|
||||
|
||||
virtual void initThermo();
|
||||
|
||||
virtual void setParameters(int n, double *c);
|
||||
virtual void getParameters(int &n, double * const c);
|
||||
|
||||
virtual void setParametersFromXML(const XML_Node& eosdata);
|
||||
|
||||
protected:
|
||||
|
||||
int m_kk;
|
||||
doublereal m_tmin, m_tmax, m_press, m_p0;
|
||||
|
||||
mutable doublereal m_tlast;
|
||||
mutable array_fp m_h0_RT;
|
||||
mutable array_fp m_cp0_R;
|
||||
mutable array_fp m_s0_R;
|
||||
|
||||
private:
|
||||
|
||||
void _updateThermo() const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -22,7 +22,8 @@
|
|||
#include "StoichSubstanceSSTP.h"
|
||||
#include "SpeciesThermo.h"
|
||||
#include <string>
|
||||
#include "importCTML.h"
|
||||
//#include "importCTML.h"
|
||||
#include "ThermoFactory.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
|
|
|
|||
303
Cantera/src/thermo/SurfPhase.cpp
Normal file
303
Cantera/src/thermo/SurfPhase.cpp
Normal file
|
|
@ -0,0 +1,303 @@
|
|||
/**
|
||||
* @file SurfPhase.cpp
|
||||
* Definitions for a simple thermoydnamics model of a surface phase derived from ThermoPhase,
|
||||
* assuming an ideal solution model
|
||||
* (see \ref thermoprops and class \link Cantera::SurfPhase SurfPhase\endlink).
|
||||
*/
|
||||
|
||||
// Copyright 2002 California Institute of Technology
|
||||
|
||||
|
||||
// turn off warnings under Windows
|
||||
#ifdef WIN32
|
||||
#pragma warning(disable:4786)
|
||||
#pragma warning(disable:4503)
|
||||
#endif
|
||||
|
||||
#include "SurfPhase.h"
|
||||
#include "EdgePhase.h"
|
||||
#include "utilities.h"
|
||||
//#include "importCTML.h"
|
||||
#include "ThermoFactory.h"
|
||||
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
//
|
||||
// class SurfPhase methods
|
||||
//
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
SurfPhase::
|
||||
SurfPhase(doublereal n0):
|
||||
ThermoPhase(),
|
||||
m_n0(n0),
|
||||
m_logn0(0.0),
|
||||
m_tmin(0.0),
|
||||
m_tmax(0.0),
|
||||
m_press(OneAtm),
|
||||
m_tlast(0.0)
|
||||
{
|
||||
if (n0 > 0.0) m_logn0 = log(n0);
|
||||
setNDim(2);
|
||||
}
|
||||
|
||||
SurfPhase::SurfPhase(XML_Node& xmlphase) {
|
||||
const XML_Node& th = xmlphase.child("thermo");
|
||||
string model = th["model"];
|
||||
if (model != "Surface") {
|
||||
throw CanteraError("SurfPhase::SurfPhase",
|
||||
"thermo model attribute must be Surface");
|
||||
}
|
||||
importPhase(xmlphase, this);
|
||||
}
|
||||
|
||||
|
||||
doublereal SurfPhase::
|
||||
enthalpy_mole() const {
|
||||
if (m_n0 <= 0.0) return 0.0;
|
||||
_updateThermo();
|
||||
return mean_X(DATA_PTR(m_h0));
|
||||
}
|
||||
|
||||
SurfPhase::
|
||||
~SurfPhase() { }
|
||||
|
||||
/*
|
||||
* For a surface phase, the pressure is not a relevant
|
||||
* thermodynamic variable, and so the Enthalpy is equal to the
|
||||
* internal energy.
|
||||
*/
|
||||
doublereal SurfPhase::
|
||||
intEnergy_mole() const { return enthalpy_mole(); }
|
||||
|
||||
void SurfPhase::
|
||||
getStandardChemPotentials(doublereal* mu0) const {
|
||||
_updateThermo();
|
||||
copy(m_mu0.begin(), m_mu0.end(), mu0);
|
||||
}
|
||||
|
||||
void SurfPhase::
|
||||
getChemPotentials(doublereal* mu) const {
|
||||
_updateThermo();
|
||||
copy(m_mu0.begin(), m_mu0.end(), mu);
|
||||
int k;
|
||||
getActivityConcentrations(DATA_PTR(m_work));
|
||||
for (k = 0; k < m_kk; k++) {
|
||||
mu[k] += GasConstant * temperature() * (log(m_work[k]) - logStandardConc(k));
|
||||
}
|
||||
}
|
||||
|
||||
void SurfPhase::
|
||||
getActivityConcentrations(doublereal* c) const {
|
||||
getConcentrations(c);
|
||||
}
|
||||
|
||||
doublereal SurfPhase::
|
||||
standardConcentration(int k) const {
|
||||
return m_n0/size(k);
|
||||
}
|
||||
|
||||
doublereal SurfPhase::
|
||||
logStandardConc(int k) const {
|
||||
return m_logn0 - m_logsize[k];
|
||||
}
|
||||
|
||||
|
||||
/// The only parameter that can be set is the site density.
|
||||
void SurfPhase::
|
||||
setParameters(int n, doublereal* c) {
|
||||
if (n != 1) {
|
||||
throw CanteraError("SurfPhase::setParameters",
|
||||
"Bad value for number of parameter");
|
||||
}
|
||||
m_n0 = c[0];
|
||||
if (m_n0 <= 0.0) {
|
||||
throw CanteraError("SurfPhase::setParameters",
|
||||
"Bad value for parameter");
|
||||
}
|
||||
m_logn0 = log(m_n0);
|
||||
}
|
||||
|
||||
void SurfPhase::
|
||||
getEnthalpy_RT(doublereal* hrt) const {
|
||||
_updateThermo();
|
||||
double rrt = 1.0/(GasConstant*temperature());
|
||||
scale(m_h0.begin(), m_h0.end(), hrt, rrt);
|
||||
}
|
||||
|
||||
void SurfPhase::
|
||||
getEntropy_R(doublereal* sr) const {
|
||||
_updateThermo();
|
||||
double rr = 1.0/GasConstant;
|
||||
scale(m_s0.begin(), m_s0.end(), sr, rr);
|
||||
}
|
||||
|
||||
void SurfPhase::
|
||||
initThermo() {
|
||||
m_h0.resize(m_kk);
|
||||
m_s0.resize(m_kk);
|
||||
m_cp0.resize(m_kk);
|
||||
m_mu0.resize(m_kk);
|
||||
m_work.resize(m_kk);
|
||||
m_pe.resize(m_kk, 0.0);
|
||||
vector_fp cov(m_kk, 0.0);
|
||||
cov[0] = 1.0;
|
||||
setCoverages(DATA_PTR(cov));
|
||||
m_logsize.resize(m_kk);
|
||||
for (int k = 0; k < m_kk; k++)
|
||||
m_logsize[k] = log(size(k));
|
||||
}
|
||||
|
||||
void SurfPhase::
|
||||
setPotentialEnergy(int k, doublereal pe) {
|
||||
m_pe[k] = pe;
|
||||
_updateThermo(true);
|
||||
}
|
||||
|
||||
void SurfPhase::
|
||||
setSiteDensity(doublereal n0) {
|
||||
doublereal x = n0;
|
||||
setParameters(1, &x);
|
||||
}
|
||||
|
||||
|
||||
//void SurfPhase::
|
||||
//setElectricPotential(doublereal V) {
|
||||
// for (int k = 0; k < m_kk; k++) {
|
||||
// m_pe[k] = charge(k)*Faraday*V;
|
||||
// }
|
||||
// _updateThermo(true);
|
||||
//}
|
||||
|
||||
|
||||
/**
|
||||
* Set the coverage fractions to a specified
|
||||
* state. This routine converts to concentrations
|
||||
* in kmol/m2, using m_n0, the surface site density,
|
||||
* and size(k), which is defined to be the number of
|
||||
* surface sites occupied by the kth molecule.
|
||||
* It then calls State::setConcentrations to set the
|
||||
* internal concentration in the object.
|
||||
*/
|
||||
void SurfPhase::
|
||||
setCoverages(const doublereal* theta) {
|
||||
double sum = 0.0;
|
||||
int k;
|
||||
for (k = 0; k < m_kk; k++) sum += theta[k];
|
||||
|
||||
for (k = 0; k < m_kk; k++) {
|
||||
m_work[k] = m_n0*theta[k]/(sum*size(k));
|
||||
}
|
||||
/*
|
||||
* Call the State:: class function
|
||||
* setConcentrations.
|
||||
*/
|
||||
setConcentrations(DATA_PTR(m_work));
|
||||
}
|
||||
|
||||
void SurfPhase::
|
||||
setCoveragesNoNorm(const doublereal* theta) {
|
||||
for (int k = 0; k < m_kk; k++) {
|
||||
m_work[k] = m_n0*theta[k]/(size(k));
|
||||
}
|
||||
/*
|
||||
* Call the State:: class function
|
||||
* setConcentrations.
|
||||
*/
|
||||
setConcentrations(DATA_PTR(m_work));
|
||||
}
|
||||
|
||||
void SurfPhase::
|
||||
getCoverages(doublereal* theta) const {
|
||||
getConcentrations(theta);
|
||||
for (int k = 0; k < m_kk; k++) {
|
||||
theta[k] *= size(k)/m_n0;
|
||||
}
|
||||
}
|
||||
|
||||
void SurfPhase::
|
||||
setCoveragesByName(std::string cov) {
|
||||
int kk = nSpecies();
|
||||
int k;
|
||||
compositionMap cc;
|
||||
for (k = 0; k < kk; k++) {
|
||||
cc[speciesName(k)] = -1.0;
|
||||
}
|
||||
parseCompString(cov, cc);
|
||||
doublereal c;
|
||||
vector_fp cv(kk, 0.0);
|
||||
for (k = 0; k < kk; k++) {
|
||||
c = cc[speciesName(k)];
|
||||
if (c > 0.0) cv[k] = c;
|
||||
}
|
||||
setCoverages(DATA_PTR(cv));
|
||||
}
|
||||
|
||||
|
||||
void SurfPhase::
|
||||
_updateThermo(bool force) const {
|
||||
doublereal tnow = temperature();
|
||||
if (m_tlast != tnow || force) {
|
||||
m_spthermo->update(tnow, DATA_PTR(m_cp0), DATA_PTR(m_h0),
|
||||
DATA_PTR(m_s0));
|
||||
m_tlast = tnow;
|
||||
doublereal rt = GasConstant * tnow;
|
||||
int k;
|
||||
for (k = 0; k < m_kk; k++) {
|
||||
m_h0[k] *= rt;
|
||||
m_s0[k] *= GasConstant;
|
||||
m_cp0[k] *= GasConstant;
|
||||
m_mu0[k] = m_h0[k] - tnow*m_s0[k];
|
||||
}
|
||||
m_tlast = tnow;
|
||||
}
|
||||
}
|
||||
|
||||
void SurfPhase::
|
||||
setParametersFromXML(const XML_Node& eosdata) {
|
||||
eosdata._require("model","Surface");
|
||||
doublereal n = getFloat(eosdata, "site_density", "-");
|
||||
if (n <= 0.0)
|
||||
throw CanteraError("SurfPhase::setParametersFromXML",
|
||||
"missing or negative site density");
|
||||
m_n0 = n;
|
||||
m_logn0 = log(m_n0);
|
||||
}
|
||||
|
||||
|
||||
void SurfPhase::setStateFromXML(const XML_Node& state) {
|
||||
|
||||
if (state.hasChild("temperature")) {
|
||||
double t = getFloat(state, "temperature", "temperature");
|
||||
setTemperature(t);
|
||||
}
|
||||
|
||||
if (state.hasChild("coverages")) {
|
||||
string comp = getString(state,"coverages");
|
||||
setCoveragesByName(comp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EdgePhase::EdgePhase(doublereal n0) : SurfPhase(n0) {
|
||||
setNDim(1);
|
||||
}
|
||||
|
||||
void EdgePhase::
|
||||
setParametersFromXML(const XML_Node& eosdata) {
|
||||
eosdata._require("model","Edge");
|
||||
doublereal n = getFloat(eosdata, "site_density", "-");
|
||||
if (n <= 0.0)
|
||||
throw CanteraError("EdgePhase::setParametersFromXML",
|
||||
"missing or negative site density");
|
||||
m_n0 = n;
|
||||
m_logn0 = log(m_n0);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
559
Cantera/src/thermo/SurfPhase.h
Normal file
559
Cantera/src/thermo/SurfPhase.h
Normal file
|
|
@ -0,0 +1,559 @@
|
|||
/**
|
||||
* @file SurfPhase.h
|
||||
* Header for a simple thermoydnamics model of a surface phase derived from ThermoPhase,
|
||||
* assuming an ideal solution model
|
||||
* (see \ref thermoprops and class \link Cantera::SurfPhase SurfPhase\endlink).
|
||||
*/
|
||||
|
||||
/* $Author$
|
||||
* $Date$
|
||||
* $Revision$
|
||||
*
|
||||
* Copyright 2002 California Institute of Technology
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CT_SURFPHASE_H
|
||||
#define CT_SURFPHASE_H
|
||||
|
||||
#include "mix_defs.h"
|
||||
#include "ThermoPhase.h"
|
||||
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
|
||||
|
||||
//! A simple thermoydnamics model for a surface phase, assuming an ideal solution model.
|
||||
/*!
|
||||
* The surface consists of a grid of equivalent sites. Surface species may be defined to
|
||||
* occupy one or more sites. The surface species are assumed to be
|
||||
* independent, and thus the species form an ideal solution.
|
||||
*
|
||||
* The density of surface sites is given by the variable \f$ n_0 \f$, which has MKS units
|
||||
* of kmol m-2.
|
||||
*
|
||||
*
|
||||
* <b> Specification of Species Standard State Properties </b>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Pressure is defined as an independent variable in this phase. However, it has
|
||||
* no effect on any quantities, as the molar concentration is a constant.
|
||||
*
|
||||
* Therefore, The standard state internal energy for species <I>k</I> is
|
||||
* equal to the enthalpy for species <I>k</I>.
|
||||
*
|
||||
* \f[
|
||||
* u^o_k = h^o_k
|
||||
* \f]
|
||||
*
|
||||
* Also, the standard state chemical potentials, entropy, and heat capacities
|
||||
* are independent of pressure. The standard state gibbs free energy is obtained
|
||||
* from the enthalpy and entropy functions.
|
||||
*
|
||||
* <b> Specification of Solution Thermodynamic Properties </b>
|
||||
*
|
||||
* The activity of species defined in the phase is given by
|
||||
* \f[
|
||||
* a_k = \theta_k
|
||||
* \f]
|
||||
*
|
||||
* The chemical potential for species <I>k</I> is equal to
|
||||
* \f[
|
||||
* \mu_k(T,P) = \mu^o_k(T) + R T \log(\theta_k)
|
||||
* \f]
|
||||
*
|
||||
* Pressure is defined as an independent variable in this phase. However, it has
|
||||
* no effect on any quantities, as the molar concentration is a constant.
|
||||
*
|
||||
* The internal energy for species k is equal to the enthalpy for species <I>k</I>
|
||||
* \f[
|
||||
* u_k = h_k
|
||||
* \f]
|
||||
*
|
||||
* The entropy for the phase is given by the following relation, which is
|
||||
* independent of the pressure:
|
||||
*
|
||||
* \f[
|
||||
* s_k(T,P) = s^o_k(T) - R \log(\theta_k)
|
||||
* \f]
|
||||
*
|
||||
* <b> Application within %Kinetics Managers </b>
|
||||
*
|
||||
* The activity concentration,\f$ C^a_k \f$, used by the kinetics manager, is equal to
|
||||
* the actual concentration, \f$ C^s_k \f$, and is given by the following
|
||||
* expression.
|
||||
* \f[
|
||||
* C^a_k = C^s_k = \frac{\theta_k n_0}{s_k}
|
||||
* \f]
|
||||
*
|
||||
* The standard concentration for species <I>k</I> is:
|
||||
* \f[
|
||||
* C^0_k = \frac{n_0}{s_k}
|
||||
* \f]
|
||||
*
|
||||
* <b> Instantiation of the Class </b>
|
||||
*
|
||||
* The constructor for this phase is located in the default ThermoFactory
|
||||
* for Cantera. A new SurfPhase may be created by the following code snippet:
|
||||
*
|
||||
* @code
|
||||
* XML_Node *xc = get_XML_File("diamond.xml");
|
||||
* XML_Node * const xs = xc->findNameID("phase", "diamond_100");
|
||||
* ThermoPhase *diamond100TP_tp = newPhase(*xs);
|
||||
* SurfPhase *diamond100TP = dynamic_cast <SurfPhase *>(diamond100TP_tp);
|
||||
* @endcode
|
||||
*
|
||||
* or by the following constructor:
|
||||
*
|
||||
* @code
|
||||
* XML_Node *xc = get_XML_File("diamond.xml");
|
||||
* XML_Node * const xs = xc->findNameID("phase", "diamond_100");
|
||||
* SurfPhase *diamond100TP = new SurfPhase(*xs);
|
||||
* @endcode
|
||||
*
|
||||
* <b> XML Example </b>
|
||||
*
|
||||
* An example of an XML Element named phase setting up a SurfPhase object named diamond_100
|
||||
* is given below.
|
||||
*
|
||||
* @verbatim
|
||||
* <phase dim="2" id="diamond_100">
|
||||
* <elementArray datasrc="elements.xml">H C</elementArray>
|
||||
* <speciesArray datasrc="#species_data">c6HH c6H* c6*H c6** c6HM c6HM* c6*M c6B </speciesArray>
|
||||
* <reactionArray datasrc="#reaction_data"/>
|
||||
* <state>
|
||||
* <temperature units="K">1200.0</temperature>
|
||||
* <coverages>c6H*:0.1, c6HH:0.9</coverages>
|
||||
* </state>
|
||||
* <thermo model="Surface">
|
||||
* <site_density units="mol/cm2">3e-09</site_density>
|
||||
* </thermo>
|
||||
* <kinetics model="Interface"/>
|
||||
* <transport model="None"/>
|
||||
* <phaseArray>
|
||||
* gas_phase diamond_bulk
|
||||
* </phaseArray>
|
||||
* </phase>
|
||||
*
|
||||
* @endverbatim
|
||||
*
|
||||
* The model attribute, "Surface", on the thermo element identifies the phase as being
|
||||
* a SurfPhase object.
|
||||
*
|
||||
* @ingroup thermoprops
|
||||
*/
|
||||
class SurfPhase : public ThermoPhase {
|
||||
|
||||
public:
|
||||
|
||||
//! Constructor.
|
||||
/*!
|
||||
* @param n0 Site Density of the Surface Phase
|
||||
* Units: kmol m-2.
|
||||
*/
|
||||
SurfPhase(doublereal n0 = 0.0);
|
||||
|
||||
//! Constructor.
|
||||
/*!
|
||||
* @param xmlphase XML node pointing to a SurfPhase description
|
||||
*/
|
||||
SurfPhase(XML_Node& xmlphase);
|
||||
|
||||
|
||||
//! Destructor.
|
||||
virtual ~SurfPhase();
|
||||
|
||||
//----- reimplimented methods of class ThermoPhase ------
|
||||
|
||||
//! Equation of state type flag.
|
||||
/*!
|
||||
* Redefine this to return cSurf, listed in mix_defs.h.
|
||||
*/
|
||||
virtual int eosType() const { return cSurf; }
|
||||
|
||||
//! Return the Molar Enthalpy. Units: J/kmol.
|
||||
/*!
|
||||
* For an ideal solution,
|
||||
* \f[
|
||||
* \hat h(T,P) = \sum_k X_k \hat h^0_k(T),
|
||||
* \f]
|
||||
* and is a function only of temperature.
|
||||
* The standard-state pure-species Enthalpies
|
||||
* \f$ \hat h^0_k(T) \f$ are computed by the species thermodynamic
|
||||
* property manager.
|
||||
*
|
||||
* \see SpeciesThermo
|
||||
*/
|
||||
virtual doublereal enthalpy_mole() const;
|
||||
|
||||
//! Return the Molar Internal Energy. Units: J/kmol
|
||||
/**
|
||||
* For a surface phase, the pressure is not a relevant
|
||||
* thermodynamic variable, and so the Enthalpy is equal to the
|
||||
* Internal Energy.
|
||||
*/
|
||||
virtual doublereal intEnergy_mole() const;
|
||||
|
||||
//! Get the array of chemical potentials at unit activity for the
|
||||
//! standard state species at the current <I>T</I> and <I>P</I> of the solution.
|
||||
/*!
|
||||
* 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;
|
||||
|
||||
//! Get the species chemical potentials. Units: J/kmol.
|
||||
/*!
|
||||
* This function returns a vector of chemical potentials of the
|
||||
* species in solution at the current temperature, pressure
|
||||
* and mole fraction of the solution.
|
||||
*
|
||||
* @param mu Output vector of species chemical
|
||||
* potentials. Length: m_kk. Units: J/kmol
|
||||
*/
|
||||
virtual void getChemPotentials(doublereal* mu) const;
|
||||
|
||||
//! Return a vector of activity concentrations for each species
|
||||
/*!
|
||||
* For this phase the activity concentrations,\f$ C^a_k \f$, are defined to be
|
||||
* equal to the actual concentrations, \f$ C^s_k \f$.
|
||||
* Activity concentrations are
|
||||
*
|
||||
* \f[
|
||||
* C^a_k = C^s_k = \frac{\theta_k n_0}{s_k}
|
||||
* \f]
|
||||
*
|
||||
* where \f$ \theta_k \f$ is the surface site fraction for species k,
|
||||
* \f$ n_0 \f$ is the surface site density for the phase, and
|
||||
* \f$ s_k \f$ is the surface size of species k.
|
||||
*
|
||||
* \f$ C^a_k\f$ that 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 concentrations are used
|
||||
* by kinetics manager classes to compute the forward and
|
||||
* reverse rates of elementary reactions. Note that they may
|
||||
* or may not have units of concentration --- they might be
|
||||
* partial pressures, mole fractions, or surface coverages,
|
||||
*
|
||||
* @param c vector of activity concentration (kmol m-2).
|
||||
*/
|
||||
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.
|
||||
* For this phase, the standard concentration is species-
|
||||
* specific
|
||||
*
|
||||
* \f[
|
||||
* C^0_k = \frac{n_0}{s_k}
|
||||
* \f]
|
||||
*
|
||||
* This definition implies that the activity is equal to \f$ \theta_k \f$.
|
||||
*
|
||||
* @param k Optional parameter indicating the species. The default
|
||||
* is to assume this refers to species 0.
|
||||
* @return
|
||||
* Returns the standard Concentration in units of m3 kmol-1.
|
||||
*/
|
||||
virtual doublereal standardConcentration(int k = 0) const;
|
||||
|
||||
//! Return the log of the standard concentration for the kth species
|
||||
/*!
|
||||
* @param k species index (default 0)
|
||||
*/
|
||||
virtual doublereal logStandardConc(int k=0) const;
|
||||
|
||||
//! Set the equation of state parameters from the argument list
|
||||
/*!
|
||||
* @internal
|
||||
* Set equation of state parameters.
|
||||
*
|
||||
* @param n number of parameters. Must be one
|
||||
* @param c array of \a n coefficients
|
||||
* c[0] = The site density (kmol m-2)
|
||||
*/
|
||||
virtual void setParameters(int n, doublereal* c);
|
||||
|
||||
//! Set the Equation-of-State parameters by reading an XML Node Input
|
||||
/*!
|
||||
*
|
||||
* The Equation-of-State data consists of one item, the site density.
|
||||
*
|
||||
* @param thermoData Reference to an XML_Node named thermo
|
||||
* containing the equation-of-state data. The
|
||||
* XML_Node is within the phase XML_Node describing
|
||||
* the %SurfPhase object.
|
||||
*
|
||||
* An example of the contents of the thermoData XML_Node is provided
|
||||
* below. The units attribute is used to supply the units of the
|
||||
* site density in any convenient form. Internally it is changed
|
||||
* into MKS form.
|
||||
*
|
||||
* @verbatim
|
||||
* <thermo model="Surface">
|
||||
* <site_density units="mol/cm2"> 3e-09 </site_density>
|
||||
* </thermo>
|
||||
* @endverbatim
|
||||
*/
|
||||
virtual void setParametersFromXML(const XML_Node& thermoData);
|
||||
|
||||
|
||||
//! Initialize the SurfPhase object after all species have been set up
|
||||
/*!
|
||||
* @internal Initialize.
|
||||
*
|
||||
* This method is provided to allow
|
||||
* subclasses to perform any initialization required after all
|
||||
* species have been added. For example, it might be used to
|
||||
* resize internal work arrays that must have an entry for
|
||||
* each species. The base class implementation does nothing,
|
||||
* and subclasses that do not require initialization do not
|
||||
* need to overload this method. When importing a CTML phase
|
||||
* description, this method is called from ThermoPhase::initThermoXML(),
|
||||
* which is called from importPhase(),
|
||||
* just prior to returning from function importPhase().
|
||||
*
|
||||
* @see importCTML.cpp
|
||||
*/
|
||||
virtual void initThermo();
|
||||
|
||||
|
||||
//! Set the initial state of the Surface Phase from an XML_Node
|
||||
/*!
|
||||
* State variables that can be set by this routine are
|
||||
* the temperature and the surface site coverages.
|
||||
*
|
||||
* @param state XML_Node containing the state information
|
||||
*
|
||||
* An example of the XML code block is given below.
|
||||
*
|
||||
* @verbatim
|
||||
* <state>
|
||||
* <temperature units="K">1200.0</temperature>
|
||||
* <coverages>c6H*:0.1, c6HH:0.9</coverages>
|
||||
* </state>
|
||||
* @endverbatim
|
||||
*/
|
||||
virtual void setStateFromXML(const XML_Node& state);
|
||||
|
||||
//! Returns the site density
|
||||
/*!
|
||||
* Site density kmol m-2
|
||||
*/
|
||||
doublereal siteDensity(){ return m_n0; }
|
||||
|
||||
//! Sets the potential energy of species k.
|
||||
/*!
|
||||
*
|
||||
* @param k Species index
|
||||
* @param pe Value of the potential energy (J kmol-1)
|
||||
*/
|
||||
void setPotentialEnergy(int k, doublereal pe);
|
||||
|
||||
//! Return the potential energy of species k.
|
||||
/*!
|
||||
* Returns the potential energy of species, k,
|
||||
* J kmol-1
|
||||
*
|
||||
* @param k Species index
|
||||
*/
|
||||
doublereal potentialEnergy(int k) {return m_pe[k];}
|
||||
|
||||
//! Set the site density of the surface phase (kmol m-2)
|
||||
/*!
|
||||
* @param n0 Site density of the surface phase (kmol m-2)
|
||||
*/
|
||||
void setSiteDensity(doublereal n0);
|
||||
|
||||
//! Get the nondimensional Enthalpy functions for the species standard states
|
||||
//! at their standard states at the current <I>T</I> and <I>P</I> of the solution.
|
||||
/*!
|
||||
* @param hrt Output vector of nondimensional standard state enthalpies.
|
||||
* Length: m_kk.
|
||||
*/
|
||||
void getEnthalpy_RT(doublereal* hrt) const;
|
||||
|
||||
//! Get the array of nondimensional Entropy functions for the
|
||||
//! species standard states at the current <I>T</I> and <I>P</I> of the solution.
|
||||
/*!
|
||||
* @param sr Output vector of nondimensional standard state entropies.
|
||||
* Length: m_kk.
|
||||
*/
|
||||
void getEntropy_R(doublereal* sr) const;
|
||||
|
||||
//! Return the thermodynamic pressure (Pa).
|
||||
/*!
|
||||
* This method must be overloaded in derived classes. Since the
|
||||
* mass density, temperature, and mass fractions are stored,
|
||||
* this method should use these values to implement the
|
||||
* mechanical equation of state \f$ P(T, \rho, Y_1, \dots,
|
||||
* Y_K) \f$.
|
||||
*/
|
||||
virtual doublereal pressure() const {
|
||||
return m_press;
|
||||
}
|
||||
|
||||
//! Set the internally storred pressure (Pa) at constant
|
||||
//! temperature and composition
|
||||
/*!
|
||||
* This method must be reimplemented in derived classes, where it
|
||||
* may involve the solution of a nonlinear equation. Within %Cantera,
|
||||
* the independent variable is the density. Therefore, this function
|
||||
* solves for the density that will yield the desired input pressure.
|
||||
* The temperature and composition iare held constant during this process.
|
||||
*
|
||||
* This base class function will print an error, if not overwritten.
|
||||
*
|
||||
* @param p input Pressure (Pa)
|
||||
*/
|
||||
virtual void setPressure(doublereal p) {
|
||||
m_press = p;
|
||||
}
|
||||
|
||||
|
||||
//------- new methods defined in this class ----------
|
||||
|
||||
//! Set the surface site fractions to a specified state.
|
||||
/*!
|
||||
* This routine converts to concentrations
|
||||
* in kmol/m2, using m_n0, the surface site density,
|
||||
* and size(k), which is defined to be the number of
|
||||
* surface sites occupied by the kth molecule.
|
||||
* It then calls State::setConcentrations to set the
|
||||
* internal concentration in the object.
|
||||
*
|
||||
* @param theta This is the surface site fraction
|
||||
* for the kth species in the surface phase.
|
||||
* This is a dimensionless quantity.
|
||||
*
|
||||
* This routine normalizes the theta's to 1, before application
|
||||
*/
|
||||
void setCoverages(const doublereal* theta);
|
||||
|
||||
//! Set the surface site fractions to a specified state.
|
||||
/*!
|
||||
* This routine converts to concentrations
|
||||
* in kmol/m2, using m_n0, the surface site density,
|
||||
* and size(k), which is defined to be the number of
|
||||
* surface sites occupied by the kth molecule.
|
||||
* It then calls State::setConcentrations to set the
|
||||
* internal concentration in the object.
|
||||
*
|
||||
* @param theta This is the surface site fraction
|
||||
* for the kth species in the surface phase.
|
||||
* This is a dimensionless quantity.
|
||||
*/
|
||||
void setCoveragesNoNorm(const doublereal* theta);
|
||||
|
||||
|
||||
//! Set the coverages from a string of colon-separated name:value pairs.
|
||||
/*!
|
||||
* @param cov String containing colon-separated name:value pairs
|
||||
*/
|
||||
void setCoveragesByName(std::string cov);
|
||||
|
||||
//! Return a vector of surface coverages
|
||||
/*!
|
||||
* Get the coverages.
|
||||
*
|
||||
* @param theta Array theta must be at least as long as
|
||||
* the number of species.
|
||||
*/
|
||||
void getCoverages(doublereal* theta) const;
|
||||
|
||||
protected:
|
||||
|
||||
//! Surface site density (kmol m-2)
|
||||
doublereal m_n0;
|
||||
|
||||
//! log of the surface site density
|
||||
doublereal m_logn0;
|
||||
|
||||
//! Minimum temperature for valid species standard state thermo props
|
||||
/*!
|
||||
* This is the minimum temperature at which all species have valid standard
|
||||
* state thermo props defined.
|
||||
*/
|
||||
doublereal m_tmin;
|
||||
|
||||
//! Maximum temperature for valid species standard state thermo props
|
||||
/*!
|
||||
* This is the maximum temperature at which all species have valid standard
|
||||
* state thermo props defined.
|
||||
*/
|
||||
doublereal m_tmax;
|
||||
|
||||
//! Current value of the pressure (Pa)
|
||||
doublereal m_press;
|
||||
|
||||
//! Current value of the temperature (Kelvin)
|
||||
mutable doublereal m_tlast;
|
||||
|
||||
//! Temporary storage for the reference state enthalpies
|
||||
mutable array_fp m_h0;
|
||||
|
||||
//! Temporary storage for the reference state entropies
|
||||
mutable array_fp m_s0;
|
||||
|
||||
//! Temporary storage for the reference state heat capacities
|
||||
mutable array_fp m_cp0;
|
||||
|
||||
//! Temporary storage for the reference state gibbs energies
|
||||
mutable array_fp m_mu0;
|
||||
|
||||
//! Temporary work array
|
||||
mutable array_fp m_work;
|
||||
|
||||
//! Potential energy of each species in the surface phase
|
||||
/*!
|
||||
* @todo Fix potential energy
|
||||
* Note, the potential energy terms seem to be orphaned at the moment.
|
||||
* They are not connected to the Gibbs free energy calculation in
|
||||
* this object
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
mutable array_fp m_pe;
|
||||
|
||||
//! vector storring the log of the size of each species.
|
||||
/*!
|
||||
* The size of each species is defined as the number of surface
|
||||
* sites each species occupies.
|
||||
*/
|
||||
mutable array_fp m_logsize;
|
||||
|
||||
private:
|
||||
|
||||
//! Update the species reference state thermodynamic functions
|
||||
/*!
|
||||
* The polynomials for the standard state functions are only
|
||||
* reevalulated if the temperature has changed.
|
||||
*
|
||||
* @param force Boolean, which if true, forces a reevalulation
|
||||
* of the thermo polynomials.
|
||||
* default = false.
|
||||
*/
|
||||
void _updateThermo(bool force=false) const;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
578
Cantera/src/thermo/ThermoFactory.cpp
Normal file
578
Cantera/src/thermo/ThermoFactory.cpp
Normal file
|
|
@ -0,0 +1,578 @@
|
|||
/**
|
||||
* @file ThermoFactory.cpp
|
||||
* Definitions for the factory class that can create known %ThermoPhase objects
|
||||
* (see \ref thermoprops and class \link Cantera::ThermoFactory ThermoFactory\endlink).
|
||||
*
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
// Copyright 2001 California Institute of Technology
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma warning(disable:4786)
|
||||
#endif
|
||||
|
||||
#include "ThermoFactory.h"
|
||||
|
||||
#include "speciesThermoTypes.h"
|
||||
#include "SpeciesThermoFactory.h"
|
||||
#include "IdealGasPhase.h"
|
||||
|
||||
#ifdef WITH_PURE_FLUIDS
|
||||
#include "PureFluidPhase.h"
|
||||
#endif
|
||||
|
||||
#include "ConstDensityThermo.h"
|
||||
#include "SurfPhase.h"
|
||||
#include "EdgePhase.h"
|
||||
|
||||
#ifdef WITH_METAL
|
||||
#include "MetalPhase.h"
|
||||
#endif
|
||||
|
||||
#undef USE_SSTP
|
||||
#ifdef WITH_STOICH_SUBSTANCE
|
||||
#ifdef USE_SSTP
|
||||
#include "StoichSubstanceSSTP.h"
|
||||
#else
|
||||
#include "StoichSubstance.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//#include "importCTML.h"
|
||||
|
||||
#ifdef WITH_LATTICE_SOLID
|
||||
#include "LatticeSolidPhase.h"
|
||||
#include "LatticePhase.h"
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
ThermoFactory* ThermoFactory::s_factory = 0;
|
||||
|
||||
static int ntypes = 9;
|
||||
static string _types[] = {"IdealGas", "Incompressible",
|
||||
"Surface", "Edge", "Metal", "StoichSubstance",
|
||||
"PureFluid", "LatticeSolid", "Lattice"};
|
||||
|
||||
static int _itypes[] = {cIdealGas, cIncompressible,
|
||||
cSurf, cEdge, cMetal, cStoichSubstance,
|
||||
cPureFluid, cLatticeSolid, cLattice};
|
||||
|
||||
/*
|
||||
* This method returns a new instance of a subclass of ThermoPhase
|
||||
*/
|
||||
ThermoPhase* ThermoFactory::newThermoPhase(std::string model) {
|
||||
|
||||
int ieos=-1;
|
||||
|
||||
for (int n = 0; n < ntypes; n++) {
|
||||
if (model == _types[n]) ieos = _itypes[n];
|
||||
}
|
||||
|
||||
ThermoPhase* th=0;
|
||||
// map<string, double> d;
|
||||
switch (ieos) {
|
||||
|
||||
case cIdealGas:
|
||||
th = new IdealGasPhase;
|
||||
break;
|
||||
|
||||
case cIncompressible:
|
||||
th = new ConstDensityThermo;
|
||||
break;
|
||||
|
||||
case cSurf:
|
||||
th = new SurfPhase;
|
||||
break;
|
||||
|
||||
case cEdge:
|
||||
th = new EdgePhase;
|
||||
break;
|
||||
|
||||
#ifdef WITH_METAL
|
||||
case cMetal:
|
||||
th = new MetalPhase;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef WITH_STOICH_SUBSTANCE
|
||||
case cStoichSubstance:
|
||||
#ifdef USE_SSTP
|
||||
th = new StoichSubstanceSSTP;
|
||||
#else
|
||||
th = new StoichSubstance;
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef WITH_LATTICE_SOLID
|
||||
case cLatticeSolid:
|
||||
th = new LatticeSolidPhase;
|
||||
break;
|
||||
|
||||
case cLattice:
|
||||
th = new LatticePhase;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef WITH_PURE_FLUIDS
|
||||
case cPureFluid:
|
||||
th = new PureFluidPhase;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
throw UnknownThermoPhaseModel("ThermoFactory::newThermoPhase",
|
||||
model);
|
||||
}
|
||||
return th;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Create a new ThermoPhase object and initializes it according to
|
||||
* the XML tree database. This routine first looks up the
|
||||
* identity of the model for the solution thermodynamics in the
|
||||
* model attribute of the thermo child of the xml phase
|
||||
* node. Then, it does a string lookup on the model to figure out
|
||||
* what ThermoPhase derived class is assigned. It creates a new
|
||||
* instance of that class, and then calls importPhase() to
|
||||
* populate that class with the correct parameters from the XML
|
||||
* tree.
|
||||
*/
|
||||
ThermoPhase* newPhase(XML_Node& xmlphase) {
|
||||
const XML_Node& th = xmlphase.child("thermo");
|
||||
string model = th["model"];
|
||||
ThermoPhase* t = newThermoPhase(model);
|
||||
importPhase(xmlphase, t);
|
||||
return t;
|
||||
}
|
||||
|
||||
ThermoPhase* newPhase(std::string infile, std::string id) {
|
||||
XML_Node* root = get_XML_File(infile);
|
||||
if (id == "-") id = "";
|
||||
XML_Node* x = get_XML_Node(string("#")+id, root);
|
||||
if (x)
|
||||
return newPhase(*x);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Import a phase specification.
|
||||
* Here we read an XML description of the phase.
|
||||
* We import descriptions of the elements that make up the
|
||||
* species in a phase.
|
||||
* We import information about the species, including their
|
||||
* reference state thermodynamic polynomials. We then freeze
|
||||
* the state of the species, and finally call initThermoXML(phase, id)
|
||||
* a member function of the ThermoPhase object to "finish"
|
||||
* the description.
|
||||
*
|
||||
*
|
||||
* @param phase This object must be the phase node of a
|
||||
* complete XML tree
|
||||
* description of the phase, including all of the
|
||||
* species data. In other words while "phase" must
|
||||
* point to an XML phase object, it must have
|
||||
* sibling nodes "speciesData" that describe
|
||||
* the species in the phase.
|
||||
* @param th Pointer to the ThermoPhase object which will
|
||||
* handle the thermodynamics for this phase.
|
||||
* We initialize part of the Thermophase object
|
||||
* here, especially for those objects which are
|
||||
* part of the Cantera Kernel.
|
||||
*/
|
||||
bool importPhase(XML_Node& phase, ThermoPhase* th,
|
||||
SpeciesThermoFactory* spfactory) {
|
||||
|
||||
// Check the the supplied XML node in fact represents a
|
||||
// phase.
|
||||
if (phase.name() != "phase")
|
||||
throw CanteraError("importPhase",
|
||||
"Current const XML_Node is not a phase element.");
|
||||
|
||||
// if no species thermo factory was supplied,
|
||||
// use the default one.
|
||||
if (!spfactory)
|
||||
spfactory = SpeciesThermoFactory::factory();
|
||||
|
||||
// set the id attribute of the phase to the 'id' attribute
|
||||
// in the XML tree.
|
||||
th->setID(phase.id());
|
||||
th->setName(phase.id());
|
||||
|
||||
// Number of spatial dimensions. Defaults to 3 (bulk phase)
|
||||
if (phase.hasAttrib("dim")) {
|
||||
int idim = intValue(phase["dim"]);
|
||||
if (idim < 1 || idim > 3)
|
||||
throw CanteraError("importPhase",
|
||||
"unphysical number of dimensions: "+phase["dim"]);
|
||||
th->setNDim(idim);
|
||||
}
|
||||
else
|
||||
th->setNDim(3); // default
|
||||
|
||||
|
||||
|
||||
// Set equation of state parameters. The parameters are
|
||||
// specific to each subclass of ThermoPhase, so this is done
|
||||
// by method setParametersFromXML in each subclass.
|
||||
if (phase.hasChild("thermo")) {
|
||||
const XML_Node& eos = phase.child("thermo");
|
||||
th->setParametersFromXML(eos);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* Add the elements.
|
||||
***************************************************************/
|
||||
th->addElementsFromXML(phase);
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* Add the species.
|
||||
*
|
||||
* Species definitions may be imported from multiple
|
||||
* sources. For each one, a speciesArray element must be
|
||||
* present.
|
||||
***************************************************************/
|
||||
XML_Node* db = 0;
|
||||
vector<XML_Node*> sparrays;
|
||||
phase.getChildren("speciesArray", sparrays);
|
||||
int jsp, nspa = static_cast<int>(sparrays.size());
|
||||
vector<XML_Node*> dbases;
|
||||
vector_int sprule(nspa,0);
|
||||
|
||||
// loop over the speciesArray elements
|
||||
for (jsp = 0; jsp < nspa; jsp++) {
|
||||
|
||||
const XML_Node& species = *sparrays[jsp];
|
||||
|
||||
// If the speciesArray element has a child element
|
||||
// <skip element="undeclared">
|
||||
// then set sprule[jsp] to 1, so
|
||||
// that any species with an undeclared element will be
|
||||
// quietly skipped when importing species.
|
||||
if (species.hasChild("skip")) {
|
||||
const XML_Node& sk = species.child("skip");
|
||||
string eskip = sk["element"];
|
||||
if (eskip == "undeclared") {
|
||||
sprule[jsp] = 1;
|
||||
}
|
||||
string dskip = sk["species"];
|
||||
if (dskip == "duplicate") {
|
||||
sprule[jsp] += 10;
|
||||
}
|
||||
}
|
||||
|
||||
string fname, idstr;
|
||||
|
||||
// get a pointer to the node containing the species
|
||||
// definitions for the species declared in this
|
||||
// speciesArray element. This may be in the local file
|
||||
// containing the phase element, or may be in another
|
||||
// file.
|
||||
db = get_XML_Node(species["datasrc"], &phase.root());
|
||||
|
||||
// add this node to the list of species database nodes.
|
||||
dbases.push_back(db);
|
||||
}
|
||||
|
||||
|
||||
// if the phase has a species thermo manager already installed,
|
||||
// delete it since we are adding new species.
|
||||
delete &th->speciesThermo();
|
||||
|
||||
// create a new species thermo manager. Function
|
||||
// 'newSpeciesThermoMgr' looks at the species in the database
|
||||
// to see what thermodynamic property parameterizations are
|
||||
// used, and selects a class that can handle the
|
||||
// parameterizations found.
|
||||
SpeciesThermo* spth = newSpeciesThermoMgr(dbases);
|
||||
|
||||
// install it in the phase object
|
||||
th->setSpeciesThermo(spth);
|
||||
SpeciesThermo& spthermo = th->speciesThermo();
|
||||
|
||||
// used to check that each species is declared only once
|
||||
map<string,bool> declared;
|
||||
|
||||
int i, k = 0;
|
||||
|
||||
// loop over the species arrays
|
||||
for (jsp = 0; jsp < nspa; jsp++) {
|
||||
|
||||
const XML_Node& species = *sparrays[jsp];
|
||||
db = dbases[jsp];
|
||||
|
||||
// Get the array of species name strings.
|
||||
vector<string> spnames;
|
||||
getStringArray(species, spnames);
|
||||
int nsp = static_cast<int>(spnames.size());
|
||||
|
||||
// if 'all' is specified, then add all species
|
||||
// defined in this database to the phase
|
||||
if (nsp == 1 && spnames[0] == "all") {
|
||||
vector<XML_Node*> allsp;
|
||||
db->getChildren("species",allsp);
|
||||
nsp = static_cast<int>(allsp.size());
|
||||
spnames.resize(nsp);
|
||||
for (int nn = 0; nn < nsp; nn++) {
|
||||
spnames[nn] = (*allsp[nn])["name"];
|
||||
}
|
||||
}
|
||||
else if (nsp == 1 && spnames[0] == "unique") {
|
||||
vector<XML_Node*> uniquesp;
|
||||
db->getChildren("species",uniquesp);
|
||||
nsp = static_cast<int>(uniquesp.size());
|
||||
spnames.clear();
|
||||
spnames.resize(nsp);
|
||||
string spnm;
|
||||
for (int nn = 0; nn < nsp; nn++) {
|
||||
spnm = (*uniquesp[nn])["name"];
|
||||
if (!declared[spnm]) spnames[nn] = spnm;
|
||||
}
|
||||
}
|
||||
|
||||
string name;
|
||||
bool skip;
|
||||
for (i = 0; i < nsp; i++) {
|
||||
name = spnames[i];
|
||||
skip = false;
|
||||
if (name == "") skip = true;
|
||||
// Check that every species is only declared once
|
||||
if (declared[name]) {
|
||||
if (sprule[jsp] >= 10)
|
||||
skip = true;
|
||||
else
|
||||
throw CanteraError("importPhase",
|
||||
"duplicate species: "+name);
|
||||
}
|
||||
if (!skip) {
|
||||
declared[name] = true;
|
||||
|
||||
// Find the species in the database by name.
|
||||
XML_Node* s = db->findByAttr("name",spnames[i]);
|
||||
if (s) {
|
||||
if (installSpecies(k, *s, *th, spthermo, sprule[jsp],
|
||||
spfactory))
|
||||
++k;
|
||||
}
|
||||
else {
|
||||
throw CanteraError("importPhase","no data for species "
|
||||
+name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// done adding species.
|
||||
th->freezeSpecies();
|
||||
|
||||
th->saveSpeciesData(db);
|
||||
|
||||
// Perform any required subclass-specific initialization.
|
||||
string id = "";
|
||||
th->initThermoXML(phase, id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// void setEOSParameters(const XML_Node& xmlphase, ThermoPhase* th) {
|
||||
|
||||
// // if no thermo model is specified for the phase, simply
|
||||
// // return
|
||||
// if (!phase.hasChild("thermo")) return;
|
||||
|
||||
// const XML_Node& eos = phase.child("thermo");
|
||||
|
||||
// // set the parameters for the particular equation of state type,
|
||||
// // and
|
||||
// if (eos["model"] == "Incompressible") {
|
||||
// if (th->eosType() == cIncompressible) {
|
||||
// doublereal rho = getFloat(eos, "density", "-");
|
||||
// th->setParameters(1, &rho);
|
||||
// }
|
||||
// else {
|
||||
// eoserror = true;
|
||||
// }
|
||||
// }
|
||||
// else if (eos["model"] == "StoichSubstance") {
|
||||
// if (th->eosType() == cStoichSubstance) {
|
||||
// doublereal rho = getFloat(eos, "density", "-");
|
||||
// th->setDensity(rho);
|
||||
// }
|
||||
// else {
|
||||
// eoserror = true;
|
||||
// }
|
||||
// }
|
||||
// else if (eos["model"] == "Surface") {
|
||||
// if (th->eosType() == cSurf) {
|
||||
// doublereal n = getFloat(eos, "site_density", "-");
|
||||
// if (n <= 0.0)
|
||||
// throw CanteraError("importCTML",
|
||||
// "missing or negative site density");
|
||||
// th->setParameters(1, &n);
|
||||
// }
|
||||
// else {
|
||||
// eoserror = true;
|
||||
// }
|
||||
// }
|
||||
// else if (eos["model"] == "Edge") {
|
||||
// if (th->eosType() == cEdge) {
|
||||
// doublereal n = getFloat(eos, "site_density", "-");
|
||||
// if (n <= 0.0)
|
||||
// throw CanteraError("importCTML",
|
||||
// "missing or negative site density");
|
||||
// th->setParameters(1, &n);
|
||||
// }
|
||||
// else {
|
||||
// eoserror = true;
|
||||
// }
|
||||
// }
|
||||
// #ifdef INCL_PURE_FLUIDS
|
||||
// else if (eos["model"] == "PureFluid") {
|
||||
// if (th->eosType() == cPureFluid) {
|
||||
// subflag = atoi(eos["fluid_type"].c_str());
|
||||
// if (subflag < 0)
|
||||
// throw CanteraError("importCTML",
|
||||
// "missing fluid type flag");
|
||||
// }
|
||||
// else {
|
||||
// eoserror = true;
|
||||
// }
|
||||
// }
|
||||
// #endif
|
||||
// if (eoserror) {
|
||||
// string msg = "Wrong equation of state type for phase "+phase["id"]+"\n";
|
||||
// msg += eos["model"]+" is not consistent with eos type "+int2str(th->eosType());
|
||||
// throw CanteraError("importCTML",msg);
|
||||
// }
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Install a species into a ThermoPhase object, which defines
|
||||
* the phase thermodynamics and speciation.
|
||||
*
|
||||
* This routine first gathers the information from the Species XML
|
||||
* tree and calls addUniqueSpecies() to add it to the
|
||||
* ThermoPhase object, p.
|
||||
* This information consists of:
|
||||
* ecomp[] = element composition of species.
|
||||
* chgr = electric charge of species
|
||||
* name = string name of species
|
||||
* sz = size of the species
|
||||
* (option double used a lot in thermo)
|
||||
*
|
||||
* Then, the routine processes the "thermo" XML element and
|
||||
* calls underlying utility routines to read the XML elements
|
||||
* containing the thermodynamic information for the reference
|
||||
* state of the species. Failures or lack of information trigger
|
||||
* an "UnknownSpeciesThermoModel" exception being thrown.
|
||||
*/
|
||||
bool installSpecies(int k, const XML_Node& s, thermo_t& p,
|
||||
SpeciesThermo& spthermo, int rule,
|
||||
SpeciesThermoFactory* factory) {
|
||||
|
||||
// get the composition of the species
|
||||
const XML_Node& a = s.child("atomArray");
|
||||
map<string,string> comp;
|
||||
getMap(a, comp);
|
||||
|
||||
// check that all elements in the species
|
||||
// exist in 'p'. If rule != 0, quietly skip
|
||||
// this species if some elements are undeclared;
|
||||
// otherwise, throw an exception
|
||||
map<string,string>::const_iterator _b = comp.begin();
|
||||
for (; _b != comp.end(); ++_b) {
|
||||
if (p.elementIndex(_b->first) < 0) {
|
||||
if (rule == 0) {
|
||||
throw CanteraError("installSpecies",
|
||||
"Species " + s["name"] +
|
||||
" contains undeclared element " + _b->first);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// construct a vector of atom numbers for each
|
||||
// element in phase p. Elements not declared in the
|
||||
// species (i.e., not in map comp) will have zero
|
||||
// entries in the vector.
|
||||
int m, nel = p.nElements();
|
||||
vector_fp ecomp(nel, 0.0);
|
||||
for (m = 0; m < nel; m++) {
|
||||
ecomp[m] = atoi(comp[p.elementName(m)].c_str());
|
||||
}
|
||||
|
||||
|
||||
// get the species charge, if any. Note that the charge need
|
||||
// not be explicitly specified if special element 'E'
|
||||
// (electron) is one of the elements.
|
||||
doublereal chrg = 0.0;
|
||||
if (s.hasChild("charge")) chrg = getFloat(s, "charge");
|
||||
|
||||
// get the species size, if any. (This is used by surface
|
||||
// phases to represent how many sites a species occupies.)
|
||||
doublereal sz = 1.0;
|
||||
if (s.hasChild("size")) sz = getFloat(s, "size");
|
||||
|
||||
// add the species to phase p.
|
||||
p.addUniqueSpecies(s["name"], &ecomp[0], chrg, sz);
|
||||
|
||||
// install the thermo parameterization for this species into
|
||||
// the species thermo manager for phase p.
|
||||
factory->installThermoForSpecies(k, s, spthermo);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Search an XML tree for species data.
|
||||
*
|
||||
* This utility routine will search the XML tree for the species
|
||||
* named by the string, kname. It will return the XML_Node
|
||||
* pointer.
|
||||
* Failures of any kind return the null pointer.
|
||||
*/
|
||||
const XML_Node *speciesXML_Node(std::string kname,
|
||||
const XML_Node *phaseSpeciesData) {
|
||||
/*
|
||||
* First look at the species database.
|
||||
* -> Look for the subelement "stoichIsMods"
|
||||
* in each of the species SS databases.
|
||||
*/
|
||||
if (!phaseSpeciesData) return ((const XML_Node *) 0);
|
||||
string jname;
|
||||
vector<XML_Node*> xspecies;
|
||||
phaseSpeciesData->getChildren("species", xspecies);
|
||||
int jj = xspecies.size();
|
||||
for (int j = 0; j < jj; j++) {
|
||||
const XML_Node& sp = *xspecies[j];
|
||||
jname = sp["name"];
|
||||
if (jname == kname) {
|
||||
return &sp;
|
||||
}
|
||||
}
|
||||
return ((const XML_Node *) 0);
|
||||
}
|
||||
|
||||
}
|
||||
229
Cantera/src/thermo/ThermoFactory.h
Normal file
229
Cantera/src/thermo/ThermoFactory.h
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
/**
|
||||
* @file ThermoFactory.h
|
||||
* Headers for the factory class that can create known %ThermoPhase objects
|
||||
* (see \ref thermoprops and class \link Cantera::ThermoFactory ThermoFactory\endlink).
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
// Copyright 2001 California Institute of Technology
|
||||
|
||||
|
||||
#ifndef THERMO_FACTORY_H
|
||||
#define THERMO_FACTORY_H
|
||||
|
||||
#include "ThermoPhase.h"
|
||||
#include "xml.h"
|
||||
#include "SpeciesThermoFactory.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
|
||||
/*!
|
||||
* @addtogroup thermoprops
|
||||
*
|
||||
* Standard %ThermoPhase objects may be instantiated by calling
|
||||
* the main %Cantera factory class for %ThermoPhase objects; This class is called ThermoFactory.
|
||||
*/
|
||||
//@{
|
||||
|
||||
//! Specific error to be thrown if the type of Thermo mananger is unrecognized.
|
||||
/*!
|
||||
* This particular error class may be caught, if the application may have other
|
||||
* models that the main Cantera appliation doesn't know about.
|
||||
*/
|
||||
class UnknownThermoPhaseModel : public CanteraError {
|
||||
public:
|
||||
//! Constructor
|
||||
/*!
|
||||
* @param proc Function name where the error occurred.
|
||||
* @param thermoModel Sting name of ThermoPhase which didn't match
|
||||
*/
|
||||
UnknownThermoPhaseModel(std::string proc, std::string thermoModel) :
|
||||
CanteraError(proc, "Specified ThermoPhase model "
|
||||
+ thermoModel +
|
||||
" does not match any known type.") {}
|
||||
//! destructor
|
||||
virtual ~UnknownThermoPhaseModel() {}
|
||||
};
|
||||
|
||||
|
||||
//! Factory class for thermodynamic property managers.
|
||||
/*!
|
||||
* This class keeps a list of the known ThermoPhase classes, and is used
|
||||
* to create new instances of these classes.
|
||||
*/
|
||||
class ThermoFactory {
|
||||
|
||||
public:
|
||||
|
||||
//! Static function that creates a static instance of the factor.
|
||||
static ThermoFactory* factory() {
|
||||
if (!s_factory) s_factory = new ThermoFactory;
|
||||
return s_factory;
|
||||
}
|
||||
|
||||
//! delete the static instance of this factory
|
||||
static void deleteFactory() {
|
||||
if (s_factory) {
|
||||
delete s_factory;
|
||||
s_factory = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//! Destructor doesn't do anything.
|
||||
/*!
|
||||
* We do not delete statically
|
||||
* created single instance of this class here, because it would
|
||||
* create an infinite loop if destructor is called for that
|
||||
* single instance.
|
||||
*/
|
||||
virtual ~ThermoFactory() { }
|
||||
|
||||
//! Create a new thermodynamic property manager.
|
||||
/*!
|
||||
* @param model String to look up the model against
|
||||
*
|
||||
* @return
|
||||
* Returns a pointer to a new ThermoPhase instance matching the
|
||||
* model string. Returns NULL if something went wrong.
|
||||
* Throws an exception UnknownThermoPhaseModel if the string
|
||||
* wasn't matched.
|
||||
*/
|
||||
virtual ThermoPhase* newThermoPhase(std::string model);
|
||||
|
||||
private:
|
||||
//! static member of a single instance
|
||||
static ThermoFactory* s_factory;
|
||||
|
||||
//! Private constructor prevents usage
|
||||
ThermoFactory(){}
|
||||
};
|
||||
|
||||
//! Create a new thermo manager instance.
|
||||
/*!
|
||||
* @param model String to look up the model against
|
||||
* @param f ThermoFactor instance to use in matching the string
|
||||
*
|
||||
* @return
|
||||
* Returns a pointer to a new ThermoPhase instance matching the
|
||||
* model string. Returns NULL if something went wrong.
|
||||
* Throws an exception UnknownThermoPhaseModel if the string
|
||||
* wasn't matched.
|
||||
*/
|
||||
inline ThermoPhase* newThermoPhase(std::string model,
|
||||
ThermoFactory* f=0) {
|
||||
if (f == 0) {
|
||||
f = ThermoFactory::factory();
|
||||
}
|
||||
return f->newThermoPhase(model);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* This routine first looks up the
|
||||
* identity of the model for the solution thermodynamics in the
|
||||
* model attribute of the thermo child of the xml phase
|
||||
* node. Then, it does a string lookup using Cantera's internal ThermoPhase Factory routines
|
||||
* on the model to figure out
|
||||
* what ThermoPhase derived class should be assigned. It creates a new
|
||||
* instance of that class, and then calls importPhase() to
|
||||
* populate that class with the correct parameters from the XML
|
||||
* tree.
|
||||
*
|
||||
* @param phase XML_Node reference pointing to the phase XML element.
|
||||
*
|
||||
* @return
|
||||
* Returns a pointer to the completed and initialized ThermoPhase object.
|
||||
*
|
||||
* @ingroup inputfiles
|
||||
*/
|
||||
ThermoPhase* newPhase(XML_Node& phase);
|
||||
ThermoPhase* newPhase(std::string infile, std::string id);
|
||||
|
||||
//! Import a phase information into an empty thermophase object
|
||||
/*!
|
||||
* Here we read an XML description of the thermodynamic information
|
||||
* for a phase. At the end of this routine, the phase should
|
||||
* be ready to be used within applications. This routine contains
|
||||
* some key routines that are used as pass back routines so that
|
||||
* the phase (and the contents of the XML file) may contain
|
||||
* variable paramerizations for the specification of the
|
||||
* species standard states, the equation of state, and the
|
||||
* specification of other nonidealities. Below, a description
|
||||
* is presented of the main algorithm for bringing up a %ThermoPhase
|
||||
* object, with care to present points where customizations
|
||||
* occur.
|
||||
*
|
||||
* Before invoking this routine, either the ThermoPhase Factory routines
|
||||
* are called or direct constructor routines are called that
|
||||
* instantiate an inherited ThermoPhase object. This object is input
|
||||
* to this routine, and therefore contains inherited routines that
|
||||
* drive the custimation of the initialization process.
|
||||
*
|
||||
* At the start of the routine, we import descriptions of the elements
|
||||
* that make up the species in a phase.
|
||||
*
|
||||
* We call setParametersFromXML(eos) to read parameters about
|
||||
* the thermo phase before the species are read in.
|
||||
*
|
||||
* We call addElementsFromXML() to add elements into the
|
||||
* description of the phase.
|
||||
*
|
||||
* We create a new species thermo manager. Function
|
||||
* 'newSpeciesThermoMgr' looks at the species in the database
|
||||
* to see what thermodynamic property parameterizations are
|
||||
* used, and selects a class that can handle the
|
||||
* parameterizations found.
|
||||
*
|
||||
* We import information about the species, including their
|
||||
* reference state thermodynamic polynomials. We then freeze
|
||||
* the state of the species in the element.
|
||||
*
|
||||
* Finally, we call initThermoXML(),
|
||||
* a member function of the ThermoPhase object, to "finish"
|
||||
* the description. Now that the species are known,
|
||||
* additional information may be read in about the thermodynamics
|
||||
* of the phase, (e.g., virial coefficients, which are
|
||||
* binary or ternary interaction parameters between species).
|
||||
*
|
||||
* @param phase This object must be the phase node of a
|
||||
* complete XML tree
|
||||
* description of the phase, including all of the
|
||||
* species data. In other words while "phase" must
|
||||
* point to an XML phase object, it must have
|
||||
* sibling nodes "speciesData" that describe
|
||||
* the species in the phase.
|
||||
* @param th Pointer to the ThermoPhase object which will
|
||||
* handle the thermodynamics for this phase.
|
||||
* We initialize part of the Thermophase object
|
||||
* here, especially for those objects which are
|
||||
* part of the Cantera Kernel.
|
||||
*
|
||||
* @param spfactory species Thermo factory pointer, if
|
||||
* available. If not available, one will be
|
||||
* created.
|
||||
*
|
||||
* @ingroup thermoprops
|
||||
*/
|
||||
bool importPhase(XML_Node& phase, ThermoPhase* th,
|
||||
SpeciesThermoFactory* spfactory = 0);
|
||||
|
||||
bool installSpecies(int k, const XML_Node& s, thermo_t& p,
|
||||
SpeciesThermo& spthermo, int rule,
|
||||
SpeciesThermoFactory* factory = 0);
|
||||
|
||||
const XML_Node *speciesXML_Node(std::string kname,
|
||||
const XML_Node *phaseSpeciesData);
|
||||
//@}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
464
Cantera/src/thermo/ThermoPhase.cpp
Normal file
464
Cantera/src/thermo/ThermoPhase.cpp
Normal file
|
|
@ -0,0 +1,464 @@
|
|||
/**
|
||||
* @file ThermoPhase.cpp
|
||||
* Definition file for class ThermoPhase, the base class for phases with
|
||||
* thermodynamic properties
|
||||
* (see class \link Cantera::ThermoPhase ThermoPhase\endlink).
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Author$
|
||||
* $Date$
|
||||
* $Revision$
|
||||
*
|
||||
* Copyright 2002 California Institute of Technology
|
||||
*
|
||||
*/
|
||||
|
||||
// turn off warnings under Windows
|
||||
#ifdef WIN32
|
||||
#pragma warning(disable:4786)
|
||||
#pragma warning(disable:4503)
|
||||
#endif
|
||||
|
||||
#include "ThermoPhase.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Cantera {
|
||||
/**
|
||||
* Copy Constructor for the ThermoPhase object.
|
||||
*
|
||||
* Currently, this is implemented, but not tested. If called it will
|
||||
* throw an exception until fully tested.
|
||||
*/
|
||||
ThermoPhase::ThermoPhase(const ThermoPhase &right) :
|
||||
Phase(),
|
||||
m_spthermo(0),
|
||||
m_speciesData(0),
|
||||
m_index(-1),
|
||||
m_phi(0.0),
|
||||
m_hasElementPotentials(false)
|
||||
{
|
||||
/*
|
||||
* Call the assignment operator
|
||||
*/
|
||||
*this = operator=(right);
|
||||
}
|
||||
|
||||
/*
|
||||
* operator=()
|
||||
*
|
||||
* Note this stuff will not work until the underlying phase
|
||||
* has a working assignment operator
|
||||
*/
|
||||
ThermoPhase& ThermoPhase::
|
||||
operator=(const ThermoPhase &right) {
|
||||
/*
|
||||
* Check for self assignment.
|
||||
*/
|
||||
if (this == &right) return *this;
|
||||
|
||||
(void)Phase::operator=(right);
|
||||
|
||||
/*
|
||||
* Pointer to the species thermodynamic property manager
|
||||
* We own this, so we need to do a deep copy
|
||||
*/
|
||||
if (m_spthermo) {
|
||||
delete m_spthermo;
|
||||
}
|
||||
//m_spthermo = (right.m_spthermo)->duplMyselfAsSpeciesThermo();
|
||||
throw CanteraError("ThermoPhase assignment", "not implemented");
|
||||
|
||||
/// Pointer to the XML tree containing the species
|
||||
/// data for this phase. This is used to access data needed to
|
||||
/// construct the transport manager and other properties
|
||||
/// later in the initialization process.
|
||||
m_speciesData = right.m_speciesData;
|
||||
|
||||
|
||||
m_index = right.m_index;
|
||||
m_phi = right.m_phi;
|
||||
m_lambdaRRT = right.m_lambdaRRT;
|
||||
m_hasElementPotentials = right.m_hasElementPotentials;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
* Duplication routine for objects which inherit from
|
||||
* ThermoPhase.
|
||||
*
|
||||
* This virtual routine can be used to duplicate thermophase objects
|
||||
* inherited from ThermoPhase even if the application only has
|
||||
* a pointer to ThermoPhase to work with.
|
||||
*
|
||||
* Currently, this is not fully implemented. If called, an
|
||||
* exception will be called by the ThermoPhase copy constructor.
|
||||
*/
|
||||
ThermoPhase *ThermoPhase::duplMyselfAsThermoPhase() {
|
||||
ThermoPhase* tp = new ThermoPhase(*this);
|
||||
return tp;
|
||||
}
|
||||
|
||||
int ThermoPhase::activityConvention() const {
|
||||
return cAC_CONVENTION_MOLAR;
|
||||
}
|
||||
|
||||
void ThermoPhase::getActivities(doublereal* a) const {
|
||||
getActivityConcentrations(a);
|
||||
int nsp = nSpecies();
|
||||
int k;
|
||||
for (k = 0; k < nsp; k++) a[k] /= standardConcentration(k);
|
||||
}
|
||||
|
||||
void ThermoPhase::setState_TPX(doublereal t, doublereal p,
|
||||
const doublereal* x) {
|
||||
setMoleFractions(x); setTemperature(t); setPressure(p);
|
||||
}
|
||||
|
||||
void ThermoPhase::setState_TPX(doublereal t, doublereal p,
|
||||
compositionMap& x) {
|
||||
setMoleFractionsByName(x); setTemperature(t); setPressure(p);
|
||||
}
|
||||
|
||||
void ThermoPhase::setState_TPX(doublereal t, doublereal p,
|
||||
const std::string& x) {
|
||||
compositionMap xx;
|
||||
int kk = nSpecies();
|
||||
for (int k = 0; k < kk; k++) xx[speciesName(k)] = -1.0;
|
||||
try {
|
||||
parseCompString(x, xx);
|
||||
}
|
||||
catch (CanteraError) {
|
||||
throw CanteraError("setState_TPX",
|
||||
"Unknown species in composition map: "+ x);
|
||||
}
|
||||
setMoleFractionsByName(xx); setTemperature(t); setPressure(p);
|
||||
}
|
||||
|
||||
void ThermoPhase::setState_TPY(doublereal t, doublereal p,
|
||||
const doublereal* y) {
|
||||
setMassFractions(y); setTemperature(t); setPressure(p);
|
||||
}
|
||||
|
||||
void ThermoPhase::setState_TPY(doublereal t, doublereal p,
|
||||
compositionMap& y) {
|
||||
setMassFractionsByName(y); setTemperature(t); setPressure(p);
|
||||
}
|
||||
|
||||
void ThermoPhase::setState_TPY(doublereal t, doublereal p,
|
||||
const std::string& y) {
|
||||
compositionMap yy;
|
||||
int kk = nSpecies();
|
||||
for (int k = 0; k < kk; k++) yy[speciesName(k)] = -1.0;
|
||||
try {
|
||||
parseCompString(y, yy);
|
||||
}
|
||||
catch (CanteraError) {
|
||||
throw CanteraError("setState_TPY",
|
||||
"Unknown species in composition map: "+ y);
|
||||
}
|
||||
setMassFractionsByName(yy); setTemperature(t); setPressure(p);
|
||||
}
|
||||
|
||||
void ThermoPhase::setState_TP(doublereal t, doublereal p) {
|
||||
setTemperature(t); setPressure(p);
|
||||
}
|
||||
|
||||
void ThermoPhase::setState_PX(doublereal p, doublereal* x) {
|
||||
setMoleFractions(x); setPressure(p);
|
||||
}
|
||||
|
||||
void ThermoPhase::setState_PY(doublereal p, doublereal* y) {
|
||||
setMassFractions(y); setPressure(p);
|
||||
}
|
||||
|
||||
void ThermoPhase::setState_HP(doublereal h, doublereal p,
|
||||
doublereal tol) {
|
||||
doublereal dt;
|
||||
setPressure(p);
|
||||
|
||||
// Newton iteration
|
||||
for (int n = 0; n < 500; n++) {
|
||||
double h0 = enthalpy_mass();
|
||||
dt = (h - h0)/cp_mass();
|
||||
// limit step size to 100 K
|
||||
if (dt > 100.0) dt = 100.0;
|
||||
else if (dt < -100.0) dt = -100.0;
|
||||
setState_TP(temperature() + dt, p);
|
||||
if (fabs(dt) < tol) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw CanteraError("setState_HP","No convergence. dt = " + fp2str(dt));
|
||||
}
|
||||
|
||||
void ThermoPhase::setState_UV(doublereal u, doublereal v,
|
||||
doublereal tol) {
|
||||
doublereal dt;
|
||||
setDensity(1.0/v);
|
||||
for (int n = 0; n < 500; n++) {
|
||||
dt = (u - intEnergy_mass())/cv_mass();
|
||||
if (dt > 100.0) dt = 100.0;
|
||||
else if (dt < -100.0) dt = -100.0;
|
||||
if (fabs(dt) < tol) {
|
||||
setTemperature(temperature() + dt);
|
||||
return;
|
||||
}
|
||||
setTemperature(temperature() + 0.5*dt);
|
||||
}
|
||||
throw CanteraError("setState_UV",
|
||||
"no convergence. dt = " + fp2str(dt)+"\n"
|
||||
+"tol = "+fp2str(tol)+"\n"
|
||||
+"u = "+fp2str(u)+" v = "+fp2str(v)+"\n");
|
||||
}
|
||||
|
||||
void ThermoPhase::setState_SP(doublereal s, doublereal p,
|
||||
doublereal tol) {
|
||||
doublereal dt;
|
||||
setPressure(p);
|
||||
for (int n = 0; n < 500; n++) {
|
||||
dt = (s - entropy_mass())*temperature()/cp_mass();
|
||||
if (dt > 100.0) dt = 100.0;
|
||||
else if (dt < -100.0) dt = -100.0;
|
||||
if (fabs(dt) < tol) {
|
||||
setState_TP(temperature() + dt, p);
|
||||
return;
|
||||
}
|
||||
setState_TP(temperature() + 0.5*dt, p);
|
||||
}
|
||||
throw CanteraError("setState_SP","no convergence. dt = " + fp2str(dt));
|
||||
}
|
||||
|
||||
void ThermoPhase::setState_SV(doublereal s, doublereal v,
|
||||
doublereal tol) {
|
||||
doublereal dt;
|
||||
setDensity(1.0/v);
|
||||
for (int n = 0; n < 500; n++) {
|
||||
dt = (s - entropy_mass())*temperature()/cv_mass();
|
||||
if (dt > 100.0) dt = 100.0;
|
||||
else if (dt < -100.0) dt = -100.0;
|
||||
if (fabs(dt) < tol) {
|
||||
setTemperature(temperature() + dt);
|
||||
return;
|
||||
}
|
||||
setTemperature(temperature() + 0.5*dt);
|
||||
}
|
||||
throw CanteraError("setState_SV","no convergence. dt = " + fp2str(dt));
|
||||
}
|
||||
|
||||
doublereal ThermoPhase::err(std::string msg) const {
|
||||
throw CanteraError("ThermoPhase","Base class method "
|
||||
+msg+" called. Equation of state type: "+int2str(eosType()));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the units of the standard and general concentrations
|
||||
* Note they have the same units, as their divisor is
|
||||
* defined to be equal to the activity of the kth species
|
||||
* in the solution, which is unitless.
|
||||
*
|
||||
* This routine is used in print out applications where the
|
||||
* units are needed. Usually, MKS units are assumed throughout
|
||||
* the program and in the XML input files.
|
||||
*
|
||||
* On return uA contains the powers of the units (MKS assumed)
|
||||
* of the standard concentrations and generalized concentrations
|
||||
* for the kth species.
|
||||
*
|
||||
* The base %ThermoPhase class assigns thedefault quantities
|
||||
* of (kmol/m3).
|
||||
* Inherited classes are responsible for overriding the default
|
||||
* values if necessary.
|
||||
*
|
||||
* uA[0] = kmol units - default = 1
|
||||
* uA[1] = m units - default = -nDim(), the number of spatial
|
||||
* dimensions in the Phase class.
|
||||
* uA[2] = kg units - default = 0;
|
||||
* uA[3] = Pa(pressure) units - default = 0;
|
||||
* uA[4] = Temperature units - default = 0;
|
||||
* uA[5] = time units - default = 0
|
||||
*/
|
||||
void ThermoPhase::getUnitsStandardConc(double *uA, int k, int sizeUA) {
|
||||
for (int i = 0; i < sizeUA; i++) {
|
||||
if (i == 0) uA[0] = 1.0;
|
||||
if (i == 1) uA[1] = -nDim();
|
||||
if (i == 2) uA[2] = 0.0;
|
||||
if (i == 3) uA[3] = 0.0;
|
||||
if (i == 4) uA[4] = 0.0;
|
||||
if (i == 5) uA[5] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* initThermoFile():
|
||||
*
|
||||
* Initialization of a phase using an xml file.
|
||||
*
|
||||
* This routine is a precursor to initThermoXML(XML_Node*)
|
||||
* routine, which does most of the work.
|
||||
*
|
||||
* @param infile XML file containing the description of the
|
||||
* phase
|
||||
*
|
||||
* @param id Optional parameter identifying the name of the
|
||||
* phase. If none is given, the first XML
|
||||
* phase element will be used.
|
||||
*/
|
||||
void ThermoPhase::initThermoFile(std::string inputFile, std::string id) {
|
||||
|
||||
if (inputFile.size() == 0) {
|
||||
throw CanteraError("ThermoPhase::initThermoFile",
|
||||
"input file is null");
|
||||
}
|
||||
string path = findInputFile(inputFile);
|
||||
ifstream fin(path.c_str());
|
||||
if (!fin) {
|
||||
throw CanteraError("initThermoFile","could not open "
|
||||
+path+" for reading.");
|
||||
}
|
||||
/*
|
||||
* The phase object automatically constructs an XML object.
|
||||
* Use this object to store information.
|
||||
*/
|
||||
XML_Node &phaseNode_XML = xml();
|
||||
XML_Node *fxml = new XML_Node();
|
||||
fxml->build(fin);
|
||||
XML_Node *fxml_phase = findXMLPhase(fxml, id);
|
||||
if (!fxml_phase) {
|
||||
throw CanteraError("ThermoPhase::initThermo",
|
||||
"ERROR: Can not find phase named " +
|
||||
id + " in file named " + inputFile);
|
||||
}
|
||||
fxml_phase->copy(&phaseNode_XML);
|
||||
initThermoXML(*fxml_phase, id);
|
||||
delete fxml;
|
||||
}
|
||||
|
||||
/*
|
||||
* Import and initialize a ThermoPhase object
|
||||
*
|
||||
* This function is called from importPhase()
|
||||
* after the elements and the
|
||||
* species are initialized with default ideal solution
|
||||
* level data.
|
||||
*
|
||||
* @param phaseNode This object must be the phase node of a
|
||||
* complete XML tree
|
||||
* description of the phase, including all of the
|
||||
* species data. In other words while "phase" must
|
||||
* point to an XML phase object, it must have
|
||||
* sibling nodes "speciesData" that describe
|
||||
* the species in the phase.
|
||||
* @param id ID of the phase. If nonnull, a check is done
|
||||
* to see if phaseNode is pointing to the phase
|
||||
* with the correct id.
|
||||
*/
|
||||
void ThermoPhase::initThermoXML(XML_Node& phaseNode, std::string id) {
|
||||
/*
|
||||
* The default implementation just calls initThermo(), which
|
||||
* inheriting classes may override.
|
||||
*/
|
||||
initThermo();
|
||||
/*
|
||||
* and sets the state
|
||||
*/
|
||||
if (phaseNode.hasChild("state")) {
|
||||
XML_Node& stateNode = phaseNode.child("state");
|
||||
setStateFromXML(stateNode);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize.
|
||||
*
|
||||
* This method is provided to allow
|
||||
* subclasses to perform any initialization required after all
|
||||
* species have been added. For example, it might be used to
|
||||
* resize internal work arrays that must have an entry for
|
||||
* each species. The base class implementation does nothing,
|
||||
* and subclasses that do not require initialization do not
|
||||
* need to overload this method. When importing a CTML phase
|
||||
* description, this method is called just prior to returning
|
||||
* from function importPhase.
|
||||
*
|
||||
* @see importCTML.cpp
|
||||
*/
|
||||
void ThermoPhase::initThermo() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the thermodynamic state.
|
||||
*/
|
||||
void ThermoPhase::setStateFromXML(const XML_Node& state) {
|
||||
|
||||
string comp = getString(state,"moleFractions");
|
||||
if (comp != "")
|
||||
setMoleFractionsByName(comp);
|
||||
else {
|
||||
comp = getString(state,"massFractions");
|
||||
if (comp != "")
|
||||
setMassFractionsByName(comp);
|
||||
}
|
||||
if (state.hasChild("temperature")) {
|
||||
double t = getFloat(state, "temperature", "temperature");
|
||||
setTemperature(t);
|
||||
}
|
||||
if (state.hasChild("pressure")) {
|
||||
double p = getFloat(state, "pressure", "pressure");
|
||||
setPressure(p);
|
||||
}
|
||||
if (state.hasChild("density")) {
|
||||
double rho = getFloat(state, "density", "density");
|
||||
setDensity(rho);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Called by function 'equilibrate' in ChemEquil.h to transfer
|
||||
* the element potentials to this object after every successful
|
||||
* equilibration routine.
|
||||
* The element potentials are storred in their dimensionless
|
||||
* forms, calculated by dividing by RT.
|
||||
* @param lambda vector containing the element potentials.
|
||||
* Length = nElements. Units are Joules/kmol.
|
||||
*/
|
||||
void ThermoPhase::setElementPotentials(const vector_fp& lambda) {
|
||||
doublereal rrt = 1.0/(GasConstant* temperature());
|
||||
int mm = nElements();
|
||||
if (lambda.size() < (size_t) mm) {
|
||||
throw CanteraError("setElementPotentials", "lambda too small");
|
||||
}
|
||||
if (!m_hasElementPotentials) {
|
||||
m_lambdaRRT.resize(mm);
|
||||
}
|
||||
for (int m = 0; m < mm; m++) {
|
||||
m_lambdaRRT[m] = lambda[m] * rrt;
|
||||
}
|
||||
m_hasElementPotentials = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the storred element potentials.
|
||||
* The element potentials are retrieved from their storred
|
||||
* dimensionless forms by multiplying by RT.
|
||||
* @param lambda Vector containing the element potentials.
|
||||
* Length = nElements. Units are Joules/kmol.
|
||||
*/
|
||||
bool ThermoPhase::getElementPotentials(doublereal* lambda) const {
|
||||
doublereal rt = GasConstant* temperature();
|
||||
int mm = nElements();
|
||||
if (m_hasElementPotentials) {
|
||||
for (int m = 0; m < mm; m++) {
|
||||
lambda[m] = m_lambdaRRT[m] * rt;
|
||||
}
|
||||
}
|
||||
return (m_hasElementPotentials);
|
||||
}
|
||||
|
||||
}
|
||||
1460
Cantera/src/thermo/ThermoPhase.h
Executable file
1460
Cantera/src/thermo/ThermoPhase.h
Executable file
File diff suppressed because it is too large
Load diff
|
|
@ -15,7 +15,8 @@
|
|||
#include "ctml.h"
|
||||
#include "WaterPDSS.h"
|
||||
#include "WaterPropsIAPWS.h"
|
||||
#include "importCTML.h"
|
||||
//#include "importCTML.h"
|
||||
#include "ThermoFactory.h"
|
||||
#include <math.h>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@
|
|||
#include "xml.h"
|
||||
#include "WaterSSTP.h"
|
||||
#include "WaterPropsIAPWS.h"
|
||||
#include "importCTML.h"
|
||||
//#include "importCTML.h"
|
||||
#include "ThermoFactory.h"
|
||||
#include <math.h>
|
||||
|
||||
namespace Cantera {
|
||||
|
|
|
|||
62
Cantera/src/thermo/mix_defs.h
Executable file
62
Cantera/src/thermo/mix_defs.h
Executable file
|
|
@ -0,0 +1,62 @@
|
|||
#ifndef CT_MIX_DEFS_H
|
||||
#define CT_MIX_DEFS_H
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
/**
|
||||
* This generic id is used as the default in virtual base
|
||||
* classes that employ id's. It is used to indicate the lack
|
||||
* of an inherited class that would define the id.
|
||||
*/
|
||||
const int cNone = 0;
|
||||
|
||||
// species thermo types
|
||||
const int cNASA = 1;
|
||||
const int cShomate = 2;
|
||||
const int cNASA96 = 3;
|
||||
|
||||
/**
|
||||
* Equation of state types:
|
||||
*
|
||||
* These types are used in the member function eosType() of
|
||||
* the virtual base class ThermoPhase. They are used to
|
||||
* distinguish different types of equation of states. Also, they
|
||||
* may be used for upcasting from the ThermoPhase class. Their
|
||||
* id's should be distinct.
|
||||
*
|
||||
* Users who wish to define their own equation of states which
|
||||
* derive from ThermoPhase should define a unique id which
|
||||
* doesn't conflict with those listed below. The Cantera Kernel
|
||||
* however, will not be know about the class and will therefore
|
||||
* not be able to initialize the class within its "factory"
|
||||
* routines.
|
||||
*/
|
||||
const int cIdealGas = 1; // IdealGasPhase in IdealGasPhase.h
|
||||
const int cIncompressible = 2; // ConstDensityThermo in ConstDensityThermo.h
|
||||
/// A surface phase. Used by class SurfPhase.
|
||||
const int cSurf = 3;
|
||||
|
||||
/// A metal phase.
|
||||
const int cMetal = 4; // MetalPhase in MetalPhase.h
|
||||
// const int cSolidCompound = 5; // SolidCompound in SolidCompound.h
|
||||
const int cStoichSubstance = 5; // StoichSubstance.h
|
||||
|
||||
const int cLatticeSolid = 20; // LatticeSolidPhase.h
|
||||
const int cLattice = 21;
|
||||
|
||||
// pure fluids with liquid/vapor eqs of state
|
||||
const int cPureFluid = 10;
|
||||
|
||||
/// An edge between two 2D surfaces
|
||||
const int cEdge = 6;
|
||||
|
||||
// kinetic manager types
|
||||
const int cGasKinetics = 2;
|
||||
const int cGRI30 = 3;
|
||||
const int cInterfaceKinetics = 4;
|
||||
const int cLineKinetics = 5;
|
||||
const int cEdgeKinetics = 6;
|
||||
const int cSolidKinetics = 7;
|
||||
}
|
||||
|
||||
#endif
|
||||
170
Cantera/src/thermo/phasereport.cpp
Normal file
170
Cantera/src/thermo/phasereport.cpp
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
|
||||
// turn off warnings under Windows
|
||||
#ifdef WIN32
|
||||
#pragma warning(disable:4786)
|
||||
#pragma warning(disable:4503)
|
||||
#endif
|
||||
|
||||
#include "ThermoPhase.h"
|
||||
#include "PureFluidPhase.h"
|
||||
#include <stdio.h>
|
||||
#include "mix_defs.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
/**
|
||||
* Format a summary of the mixture state for output.
|
||||
*/
|
||||
string report(const ThermoPhase& th, bool show_thermo) {
|
||||
|
||||
char p[200];
|
||||
string s = "";
|
||||
try {
|
||||
if (th.name() != "") {
|
||||
sprintf(p, " \n %s:\n", th.name().c_str());
|
||||
s += p;
|
||||
}
|
||||
sprintf(p, " \n temperature %12.6g K\n", th.temperature());
|
||||
s += p;
|
||||
sprintf(p, " pressure %12.6g Pa\n", th.pressure());
|
||||
s += p;
|
||||
sprintf(p, " density %12.6g kg/m^3\n", th.density());
|
||||
s += p;
|
||||
sprintf(p, " mean mol. weight %12.6g amu\n", th.meanMolecularWeight());
|
||||
s += p;
|
||||
#ifdef WITH_PURE_FLUIDS
|
||||
if (th.eosType() == cPureFluid) {
|
||||
double xx = ((PureFluidPhase*)(&th))->vaporFraction();
|
||||
// if (th.temperature() < th.critTemperature()) {
|
||||
sprintf(p, " vapor fraction %12.6g \n",
|
||||
xx); //th.vaporFraction());
|
||||
s += p;
|
||||
//}
|
||||
}
|
||||
#endif
|
||||
doublereal phi = th.electricPotential();
|
||||
if (phi != 0.0) {
|
||||
sprintf(p, " potential %12.6g V\n", phi);
|
||||
s += p;
|
||||
}
|
||||
if (show_thermo) {
|
||||
sprintf(p, " \n");
|
||||
s += p;
|
||||
sprintf(p, " 1 kg 1 kmol\n");
|
||||
s += p;
|
||||
sprintf(p, " ----------- ------------\n");
|
||||
s += p;
|
||||
sprintf(p, " enthalpy %12.6g %12.4g J\n",
|
||||
th.enthalpy_mass(), th.enthalpy_mole());
|
||||
s += p;
|
||||
sprintf(p, " internal energy %12.6g %12.4g J\n",
|
||||
th.intEnergy_mass(), th.intEnergy_mole());
|
||||
s += p;
|
||||
sprintf(p, " entropy %12.6g %12.4g J/K\n",
|
||||
th.entropy_mass(), th.entropy_mole());
|
||||
s += p;
|
||||
sprintf(p, " Gibbs function %12.6g %12.4g J\n",
|
||||
th.gibbs_mass(), th.gibbs_mole());
|
||||
s += p;
|
||||
sprintf(p, " heat capacity c_p %12.6g %12.4g J/K\n",
|
||||
th.cp_mass(), th.cp_mole());
|
||||
s += p;
|
||||
sprintf(p, " heat capacity c_v %12.6g %12.4g J/K\n",
|
||||
th.cv_mass(), th.cv_mole());
|
||||
s += p;
|
||||
}
|
||||
|
||||
int kk = th.nSpecies();
|
||||
array_fp x(kk);
|
||||
array_fp y(kk);
|
||||
array_fp mu(kk);
|
||||
th.getMoleFractions(&x[0]);
|
||||
th.getMassFractions(&y[0]);
|
||||
th.getChemPotentials(&mu[0]);
|
||||
doublereal rt = GasConstant * th.temperature();
|
||||
int k;
|
||||
if (th.nSpecies() > 1) {
|
||||
|
||||
if (show_thermo) {
|
||||
sprintf(p, " \n X "
|
||||
" Y Chem. Pot. / RT \n");
|
||||
s += p;
|
||||
sprintf(p, " ------------- "
|
||||
"------------ ------------\n");
|
||||
s += p;
|
||||
for (k = 0; k < kk; k++) {
|
||||
if (x[k] > SmallNumber) {
|
||||
sprintf(p, "%18s %12.6g %12.6g %12.6g\n",
|
||||
th.speciesName(k).c_str(), x[k], y[k], mu[k]/rt);
|
||||
}
|
||||
else {
|
||||
sprintf(p, "%18s %12.6g %12.6g \n",
|
||||
th.speciesName(k).c_str(), x[k], y[k]);
|
||||
}
|
||||
s += p;
|
||||
}
|
||||
}
|
||||
else {
|
||||
sprintf(p, " \n X"
|
||||
"Y\n");
|
||||
s += p;
|
||||
sprintf(p, " -------------"
|
||||
" ------------\n");
|
||||
s += p;
|
||||
for (k = 0; k < kk; k++) {
|
||||
sprintf(p, "%18s %12.6g %12.6g\n",
|
||||
th.speciesName(k).c_str(), x[k], y[k]);
|
||||
s += p;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (CanteraError) {
|
||||
;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void writephase(const ThermoPhase& th, bool show_thermo) {
|
||||
string s = report(th, show_thermo);
|
||||
writelog(s+"\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a composition list for output.
|
||||
*/
|
||||
string formatCompList(const Phase& mix, int xyc) {
|
||||
|
||||
const doublereal Threshold = 1.e-20;
|
||||
|
||||
char p[200];
|
||||
string s = "";
|
||||
int kk = mix.nSpecies();
|
||||
array_fp zz(kk);
|
||||
switch (xyc) {
|
||||
case 0: mix.getMoleFractions(&zz[0]); break;
|
||||
case 1: mix.getMassFractions(&zz[0]); break;
|
||||
case 2: mix.getConcentrations(&zz[0]); break;
|
||||
default: return "error: xyc must be 0, 1, or 2";
|
||||
}
|
||||
|
||||
doublereal z;
|
||||
int k;
|
||||
for (k = 0; k < kk; k++) {
|
||||
z = fabs(zz[k]);
|
||||
if (z < Threshold) zz[k] = 0.0;
|
||||
}
|
||||
|
||||
for (k = 0; k < kk; k++) {
|
||||
sprintf(p, "%18s\t %12.6e\n", mix.speciesName(k).c_str(),
|
||||
zz[k]);
|
||||
s += p;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
105
Cantera/src/thermo/speciesThermoTypes.h
Executable file
105
Cantera/src/thermo/speciesThermoTypes.h
Executable file
|
|
@ -0,0 +1,105 @@
|
|||
/**
|
||||
* @file speciesThermoTypes.h
|
||||
* Contains const definitions for types of species
|
||||
* reference-state thermodynamics managers (see \ref spthermo)
|
||||
*/
|
||||
/*
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
// Copyright 2001 California Institute of Technology
|
||||
|
||||
|
||||
#ifndef SPECIES_THERMO_TYPES_H
|
||||
#define SPECIES_THERMO_TYPES_H
|
||||
|
||||
//! Constant Cp
|
||||
#define CONSTANT_CP 1
|
||||
|
||||
//! Polynomial
|
||||
#define POLYNOMIAL_4 2
|
||||
|
||||
//! Two regions of 7 coefficient NASA Polynomials
|
||||
//! This is implemented in the class NasaPoly2 in NasaPoly2.h
|
||||
#define NASA 4
|
||||
|
||||
//! Two regions of 7 coefficient NASA Polynomials
|
||||
//! This is implemented in the class NasaPoly2 in NasaPoly2.h
|
||||
#define NASA2 4
|
||||
|
||||
//! Two regions of Shomate Polynomials.
|
||||
#define SHOMATE 8
|
||||
|
||||
//! Two regions of Shomate Polynomials.
|
||||
#define SHOMATE2 8
|
||||
|
||||
//! Tiger Polynomials. Not implemented here.
|
||||
#define TIGER 16
|
||||
|
||||
//! Constant Cp thermo.
|
||||
//! This is implemented in ConstCpPoly in constCpPoly.h for one species.
|
||||
//! If the whole phase is constcp, SimpleThermo in SimpleThermo.h
|
||||
//! implements this for the whole phase.
|
||||
#define SIMPLE 32
|
||||
|
||||
//! piecewise interpolation of mu0.
|
||||
//! This is implemented in Mu0Poly in Mu0Poly.h
|
||||
#define MU0_INTERP 64
|
||||
|
||||
//! one region of Shomate Polynomials used in NIST database
|
||||
//! This is implemented in the NIST database.
|
||||
//! This is implemented in ShomatePoly in ShomatePoly.h
|
||||
#define SHOMATE1 128
|
||||
|
||||
//! 7 coefficient NASA Polynomials
|
||||
//! This is implemented in the class NasaPoly1 in NasaPoly1.h
|
||||
#define NASA1 256
|
||||
|
||||
#include "ct_defs.h"
|
||||
|
||||
#include "stringUtils.h"
|
||||
#include "global.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
//! Error for unknown thermo parameterization
|
||||
struct UnknownThermoParam {
|
||||
//! Constructor
|
||||
/*!
|
||||
* @param thermotype Integer specifying the thermo parameterization
|
||||
*
|
||||
* @todo Is this used?
|
||||
*/
|
||||
UnknownThermoParam(int thermotype) {
|
||||
writelog(std::string("\n ### ERROR ### \n") +
|
||||
"Unknown species thermo parameterization ("
|
||||
+ int2str(thermotype) + ")\n\n");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! holds parameterization-dependent index information
|
||||
/*!
|
||||
* These are all integers.
|
||||
* @todo Is this used?
|
||||
*/
|
||||
struct ThermoIndexData {
|
||||
//! param
|
||||
int param;
|
||||
//! number of coefficients
|
||||
int nCoefficients;
|
||||
//! coefficient for Tmin
|
||||
int Tmin_coeff;
|
||||
//! coefficient for Tmax
|
||||
int Tmax_coeff;
|
||||
//! reference pressure coefficient
|
||||
int Pref_coeff;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Loading…
Add table
Reference in a new issue