cantera/Cantera/src/thermo/VPStandardStateTP.cpp
Harry Moffat ca4f9cc31d Work on VPStandardStateTP. Started to formalize what it actually
does, putting in doxygen documentation. Tried to fix some holes
in DebyeHuckel wherein calculations may be returned without
updating the underlying water standard state.
2007-03-08 18:23:52 +00:00

496 lines
14 KiB
C++

/**
*
* @file VPStandardStateTP.cpp
*/
/*
* Copywrite (2005) Sandia Corporation. Under the terms of
* Contract DE-AC04-94AL85000 with Sandia Corporation, the
* U.S. Government retains certain rights in this software.
*/
/*
* $Author$
* $Date$
* $Revision$
*/
// turn off warnings under Windows
#ifdef WIN32
#pragma warning(disable:4786)
#pragma warning(disable:4503)
#endif
#include "VPStandardStateTP.h"
using namespace std;
namespace Cantera {
/*
* Default constructor
*/
VPStandardStateTP::VPStandardStateTP() :
ThermoPhase(),
m_Pcurrent(OneAtm),
m_tlast(-1.0),
m_tlast_ref(-1.0),
m_plast(-1.0),
m_p0(OneAtm),
m_useTmpRefStateStorage(true),
m_useTmpStandardStateStorage(false)
{
}
/*
* Copy Constructor:
*
* Note this stuff will not work until the underlying phase
* has a working copy constructor.
*
* The copy constructor just calls the assignment operator
* to do the heavy lifting.
*/
VPStandardStateTP::VPStandardStateTP(const VPStandardStateTP &b) :
ThermoPhase(),
m_Pcurrent(OneAtm),
m_tlast(-1.0),
m_tlast_ref(-1.0),
m_plast(-1.0),
m_p0(OneAtm),
m_useTmpRefStateStorage(true),
m_useTmpStandardStateStorage(false)
{
*this = b;
}
/*
* operator=()
*
* Note this stuff will not work until the underlying phase
* has a working assignment operator
*/
VPStandardStateTP& VPStandardStateTP::
operator=(const VPStandardStateTP &b) {
if (&b != this) {
/*
* Mostly, this is a passthrough to the underlying
* assignment operator for the ThermoPhae parent object.
*/
ThermoPhase::operator=(b);
/*
* However, we have to handle data that we own.
*/
m_Pcurrent = b.m_Pcurrent;
m_tlast = b.m_tlast;
m_tlast_ref = b.m_tlast_ref;
m_plast = b.m_plast;
m_p0 = b.m_p0;
m_useTmpRefStateStorage = b.m_useTmpRefStateStorage;
m_h0_RT = b.m_h0_RT;
m_cp0_R = b.m_cp0_R;
m_g0_RT = b.m_g0_RT;
m_s0_R = b.m_s0_R;
m_useTmpStandardStateStorage = b.m_useTmpStandardStateStorage;
m_hss_RT = b.m_hss_RT;
m_cpss_R = b.m_cpss_R;
m_gss_RT = b.m_gss_RT;
m_sss_R = b.m_sss_R;
m_Vss = b.m_Vss;
}
return *this;
}
/*
* ~VPStandardStateTP(): (virtual)
*
* This destructor does nothing. All of the owned objects
* handle themselves.
*/
VPStandardStateTP::~VPStandardStateTP() {
}
/*
* Duplication function.
* This calls the copy constructor for this object.
*/
ThermoPhase* VPStandardStateTP::duplMyselfAsThermoPhase() {
VPStandardStateTP* vptp = new VPStandardStateTP(*this);
return (ThermoPhase *) vptp;
}
/*
* ------------Molar Thermodynamic Properties -------------------------
*/
doublereal VPStandardStateTP::err(std::string msg) const {
throw CanteraError("VPStandardStateTP","Base class method "
+msg+" called. Equation of state type: "+int2str(eosType()));
return 0;
}
/*
* ---- Partial Molar Properties of the Solution -----------------
*/
/*
* Get the array of non-dimensional species chemical potentials
* These are partial molar Gibbs free energies.
* \f$ \mu_k / \hat R T \f$.
* Units: unitless
*
* We close the loop on this function, here, calling
* getChemPotentials() and then dividing by RT.
*/
void VPStandardStateTP::getChemPotentials_RT(doublereal* muRT) const{
getChemPotentials(muRT);
doublereal invRT = 1.0 / _RT();
for (int k = 0; k < m_kk; k++) {
muRT[k] *= invRT;
}
}
/*
* ----- Thermodynamic Values for the Species Standard States States ----
*/
void VPStandardStateTP::getStandardChemPotentials(doublereal* g) const {
getGibbs_RT(g);
doublereal RT = _RT();
for (int k = 0; k < m_kk; k++) {
g[k] *= RT;
}
}
void VPStandardStateTP::getEnthalpy_RT(doublereal* hrt) const {
if (m_useTmpStandardStateStorage) {
_updateStandardStateThermo();
copy(m_hss_RT.begin(), m_hss_RT.end(), hrt);
} else {
err("getEnthalpy_RT ERROR: Must be overwritten in child classes");
_updateStandardStateThermo();
}
}
void VPStandardStateTP::getEntropy_R(doublereal* srt) const {
if (m_useTmpStandardStateStorage) {
_updateStandardStateThermo();
copy(m_sss_R.begin(), m_sss_R.end(), srt);
} else {
err("getEntropy_R ERROR: Must be overwritten in child classes");
_updateStandardStateThermo();
}
}
void VPStandardStateTP::getGibbs_RT(doublereal* grt) const {
if (m_useTmpStandardStateStorage) {
_updateStandardStateThermo();
copy(m_gss_RT.begin(), m_gss_RT.end(), grt);
} else {
err("getGibbs_RT ERROR: Must be overwritten in child classes");
_updateStandardStateThermo();
}
}
void VPStandardStateTP::getPureGibbs(doublereal* g) const {
getGibbs_RT(g);
doublereal RT = _RT();
for (int k = 0; k < m_kk; k++) {
g[k] *= RT;
}
}
void VPStandardStateTP::getIntEnergy_RT(doublereal* urt) const {
if (m_useTmpStandardStateStorage) {
_updateStandardStateThermo();
copy(m_hss_RT.begin(), m_hss_RT.end(), urt);
doublereal RT = _RT();
doublereal tmp = pressure() / RT;
for (int k = 0; k < m_kk; k++) {
urt[k] -= tmp * m_Vss[k];
}
} else {
err("getIntEnergy_RT ERROR: Must be overwritten in child classes");
_updateStandardStateThermo();
}
}
void VPStandardStateTP::getCp_R(doublereal* cpr) const {
if (m_useTmpStandardStateStorage) {
_updateStandardStateThermo();
copy(m_cpss_R.begin(), m_cpss_R.end(), cpr);
} else {
err("getCp_R ERROR: Must be overwritten in child classes");
_updateStandardStateThermo();
}
}
void VPStandardStateTP::getStandardVolumes(doublereal *vol) const {
if (m_useTmpStandardStateStorage) {
_updateStandardStateThermo();
copy(m_Vss.begin(), m_Vss.end(), vol);
} else {
err("getStandardVolumes ERROR: Must be overwritten in child classes");
_updateStandardStateThermo();
}
}
/*
* ----- 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.
*/
void VPStandardStateTP::getEnthalpy_RT_ref(doublereal *hrt) const {
if (m_useTmpRefStateStorage) {
/*
* Call the function that makes sure the local copy of the
* species reference thermo functions are up to date for the
* current temperature.
*/
_updateRefStateThermo();
/*
* Copy the enthalpy function into return vector.
*/
copy(m_h0_RT.begin(), m_h0_RT.end(), hrt);
} else if (m_useTmpStandardStateStorage) {
_updateStandardStateThermo(m_p0);
copy(m_hss_RT.begin(), m_hss_RT.end(), hrt);
} else {
err("getEnthalpy_RT_ref() ERROR: not handled");
}
}
/*
* Returns the vector of nondimensional
* enthalpies of the reference state at the current temperature
* of the solution and the reference pressure for the species.
*/
void VPStandardStateTP::getGibbs_RT_ref(doublereal *grt) const {
if (m_useTmpRefStateStorage) {
/*
* Call the function that makes sure the local copy of
* the species reference thermo functions are up to date
* for the current temperature.
*/
_updateRefStateThermo();
/*
* Copy the gibbs function into return vector.
*/
copy(m_g0_RT.begin(), m_g0_RT.end(), grt);
} else if (m_useTmpStandardStateStorage) {
_updateStandardStateThermo(m_p0);
copy(m_gss_RT.begin(), m_gss_RT.end(), grt);
} else {
err("getGibbs_RT_ref() ERROR: not handled");
}
}
/*
* 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 is filled in here so that derived classes don't have to
* take care of it.
*/
void VPStandardStateTP::getGibbs_ref(doublereal *g) const {
getGibbs_RT_ref(g);
double RT = _RT();
for (int k = 0; k < m_kk; k++) {
g[k] *= RT;
}
}
/*
* Returns the vector of nondimensional
* entropies of the reference state at the current temperature
* of the solution and the reference pressure for the species.
*/
void VPStandardStateTP::getEntropy_R_ref(doublereal *er) const {
if (m_useTmpRefStateStorage) {
/*
* Call the function that makes sure the local copy of
* the species reference thermo functions are up to date
* for the current temperature.
*/
_updateRefStateThermo();
/*
* Copy the gibbs function into return vector.
*/
copy(m_s0_R.begin(), m_s0_R.end(), er);
} else if (m_useTmpStandardStateStorage) {
_updateStandardStateThermo(m_p0);
copy(m_sss_R.begin(), m_sss_R.end(), er);
} else {
err("getEntropy_R_ref() ERROR: not handled");
}
}
/*
* Returns the vector of nondimensional
* constant pressure heat capacities of the reference state
* at the current temperature of the solution
* and reference pressure for the species.
*/
void VPStandardStateTP::getCp_R_ref(doublereal *cpr) const {
if (m_useTmpRefStateStorage) {
/*
* Call the function that makes sure the local copy of
* the species reference thermo functions are up to date
* for the current temperature.
*/
_updateRefStateThermo();
/*
* Copy the gibbs function into return vector.
*/
copy(m_cp0_R.begin(), m_cp0_R.end(), cpr);
} else if (m_useTmpStandardStateStorage) {
_updateStandardStateThermo(m_p0);
copy(m_cpss_R.begin(), m_cpss_R.end(), cpr);
} else {
err("getCp_R_ref() ERROR: not handled");
}
}
/*
* Get the molar volumes of the species reference states at the current
* <I>T</I> and <I>P_ref</I> of the solution.
*
* units = m^3 / kmol
*/
void VPStandardStateTP::getStandardVolumes_ref(doublereal *vol) const {
if (m_useTmpStandardStateStorage) {
_updateStandardStateThermo(m_p0);
copy(m_Vss.begin(), m_Vss.end(), vol);
} else {
err("getStandardVolumes_ref() ERROR: not handled");
}
}
/*
* Perform initializations after all species have been
* added.
*/
void VPStandardStateTP::initThermo() {
initLengths();
ThermoPhase::initThermo();
}
/*
* Initialize the internal lengths.
* (this is not a virtual function)
*/
void VPStandardStateTP::initLengths() {
m_kk = nSpecies();
int leng = m_kk;
if (m_useTmpRefStateStorage){
m_h0_RT.resize(leng);
m_g0_RT.resize(leng);
m_cp0_R.resize(leng);
m_s0_R.resize(leng);
}
if (m_useTmpStandardStateStorage) {
m_hss_RT.resize(leng);
m_gss_RT.resize(leng);
m_cpss_R.resize(leng);
m_sss_R.resize(leng);
m_Vss.resize(leng);
}
}
/*
* Import and initialize a ThermoPhase object
*
* 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.
*
* This routine initializes the lengths in the current object and
* then calls the parent routine.
*/
void VPStandardStateTP::initThermoXML(XML_Node& phaseNode, std::string id) {
VPStandardStateTP::initLengths();
ThermoPhase::initThermoXML(phaseNode, id);
}
/*
* void _updateRefStateThermo() (protected, virtual, const)
*
* This function checks to see whether the temperature has changed and
* thus the reference thermodynamics functions for all of the species
* must be recalculated.
* It must be called for every reference state function evaluation,
* if m_useTmpRefStateStorage is set to true.
* If the temperature has changed, the species thermo manager is called
* to recalculate the following internal arrays at the current temperature and at
* the reference pressure:
*
* - m_h0_RT
* - m_g0_RT
* - m_s0_R
* - m_cp0_R
*
* This function may be reimplemented in child objects. However, it doesn't
* necessarily have to be, if the species thermo manager can carry
* out the full calculation.
*/
void VPStandardStateTP::_updateRefStateThermo() const {
if (m_spthermo) {
doublereal tnow = temperature();
if (m_tlast_ref != tnow) {
m_spthermo->update(tnow, DATA_PTR(m_cp0_R), DATA_PTR(m_h0_RT),
DATA_PTR(m_s0_R));
m_tlast_ref = tnow;
for (int k = 0; k < m_kk; k++) {
m_g0_RT[k] = m_h0_RT[k] - m_s0_R[k];
}
}
}
}
/*
* void _updateStandardStateThermo() (protected, virtual, const)
*
* If m_useTmpStandardStateStorage is true,
* This function must be called for every call to functions in this
* class that need standard state properties.
* Child classes may require that it be called even if m_useTmpStandardStateStorage
* is not true.
* It checks to see whether the temperature has changed and
* thus the ss thermodynamics functions for all of the species
* must be recalculated.
*
* This
*/
void VPStandardStateTP::_updateStandardStateThermo(doublereal pnow) const {
_updateRefStateThermo();
doublereal tnow = temperature();
if (pnow == -1.0) {
pnow = pressure();
}
if (m_tlast != tnow || m_plast != pnow) {
err("_updateStandardStateThermo ERROR: Must be overwritten in child classes");
/*
* Redo objects that need reevaluation.
*/
for (int k = 0; k < m_kk; k++) {
m_g0_RT[k] = m_g0_RT[k];
}
m_tlast = tnow;
m_plast = pnow;
}
}
}