diff --git a/Cantera/src/thermo/DebyeHuckel.cpp b/Cantera/src/thermo/DebyeHuckel.cpp index 28bc83353..b71db7408 100644 --- a/Cantera/src/thermo/DebyeHuckel.cpp +++ b/Cantera/src/thermo/DebyeHuckel.cpp @@ -24,7 +24,7 @@ //#include "importCTML.h" #include "ThermoFactory.h" #include "WaterProps.h" -#include "WaterPDSS.h" +#include "PDSS_Water.h" #include using namespace std; @@ -49,8 +49,7 @@ namespace Cantera { m_densWaterSS(1000.), m_waterProps(0) { - m_useTmpRefStateStorage = true; - m_useTmpStandardStateStorage = false; + m_npActCoeff.resize(3); m_npActCoeff[0] = 0.1127; m_npActCoeff[1] = -0.01049; @@ -80,8 +79,6 @@ namespace Cantera { m_densWaterSS(1000.), m_waterProps(0) { - m_useTmpRefStateStorage = true; - m_useTmpStandardStateStorage = false; m_npActCoeff.resize(3); m_npActCoeff[0] = 0.1127; m_npActCoeff[1] = -0.01049; @@ -104,8 +101,6 @@ namespace Cantera { m_densWaterSS(1000.), m_waterProps(0) { - m_useTmpRefStateStorage = true; - m_useTmpStandardStateStorage = false; m_npActCoeff.resize(3); m_npActCoeff[0] = 0.1127; m_npActCoeff[1] = -0.01049; @@ -164,21 +159,23 @@ namespace Cantera { m_B_Debye = b.m_B_Debye; m_B_Dot = b.m_B_Dot; m_npActCoeff = b.m_npActCoeff; - if (m_waterSS) { - delete m_waterSS; - m_waterSS = 0; - } - if (b.m_waterSS) { - m_waterSS = new WaterPDSS(*(b.m_waterSS)); + + // This is an internal shallow copy of the PDSS_Water pointer + m_waterSS = dynamic_cast(providePDSS(0)) ; + if (!m_waterSS) { + throw CanteraError("DebyHuckel::operator=()", "Dynamic cast to waterPDSS failed"); } + m_densWaterSS = b.m_densWaterSS; + if (m_waterProps) { delete m_waterProps; m_waterProps = 0; } if (b.m_waterProps) { - m_waterProps = new WaterProps(*(b.m_waterProps)); + m_waterProps = new WaterProps(m_waterSS); } + m_expg0_RT = b.m_expg0_RT; m_pe = b.m_pe; m_pp = b.m_pp; @@ -202,9 +199,6 @@ namespace Cantera { if (m_waterProps) { delete m_waterProps; m_waterProps = 0; } - if (m_waterSS) { - delete m_waterSS; m_waterSS = 0; - } } /* @@ -855,296 +849,9 @@ namespace Cantera { } } - /* - * -------- Properties of the Standard State of the Species - * in the Solution ------------------ - */ - /* - * getStandardChemPotentials() (virtual, const) - * - * - * Get the standard state chemical potentials of the species. - * This is the array of chemical potentials at unit activity - * (Mole fraction scale) - * \f$ \mu^0_k(T,P) \f$. - * We define these here as the chemical potentials of the pure - * species at the temperature and pressure of the solution. - * This function is used in the evaluation of the - * equilibrium constant Kc. Therefore, Kc will also depend - * on T and P. This is the norm for liquid and solid systems. - * - * units = J / kmol - */ - void DebyeHuckel::getStandardChemPotentials(doublereal* mu) const { - _updateStandardStateThermo(); - getGibbs_ref(mu); - doublereal pref; - doublereal delta_p; - for (int k = 0; k < m_kk; k++) { - pref = m_spthermo->refPressure(k); - delta_p = m_Pcurrent - pref; - mu[k] += delta_p * m_speciesSize[k]; - } - if (m_waterSS) { - mu[0] = m_waterSS->gibbs_mole(); - } - } - - /* - * Get the nondimensional gibbs function for the species - * standard states at the current T and P of the solution. - * - * \f[ - * \mu^0_k(T,P) = \mu^{ref}_k(T) + (P - P_{ref}) * V_k - * \f] - * where \f$V_k\f$ is the molar volume of pure species k. - * \f$ \mu^{ref}_k(T)\f$ is the chemical potential of pure - * species k at the reference pressure, \f$P_{ref}\f$. - * - * @param grt Vector of length m_kk, which on return sr[k] - * will contain the nondimensional - * standard state gibbs function for species k. - */ - void DebyeHuckel::getGibbs_RT(doublereal* grt) const { - _updateStandardStateThermo(); - getPureGibbs(grt); - doublereal invRT = 1.0 / _RT(); - for (int k = 0; k < m_kk; k++) { - grt[k] *= invRT; - } - } - - /* - * - * getPureGibbs() - * - * Get the Gibbs functions for the pure species - * at the current T and P of the solution. - * We assume an incompressible constant partial molar - * volume here: - * \f[ - * \mu^0_k(T,p) = \mu^{ref}_k(T) + (P - P_{ref}) * V_k - * \f] - * where \f$V_k\f$ is the molar volume of pure species k<\I>. - * \f$ u^{ref}_k(T)\f$ is the chemical potential of pure - * species k<\I> at the reference pressure, \f$P_{ref}\f$. - */ - void DebyeHuckel::getPureGibbs(doublereal* gpure) const { - getStandardChemPotentials(gpure); - } - - /* - * Get the array of nondimensional Enthalpy functions for the ss - * species at the current T and P of the solution. - * We assume an incompressible constant partial molar - * volume here: - * \f[ - * h^0_k(T,P) = h^{ref}_k(T) + (P - P_{ref}) * V_k - * \f] - * where \f$V_k\f$ is the molar volume of SS species k<\I>. - * \f$ h^{ref}_k(T)\f$ is the enthalpy of the SS - * species k<\I> at the reference pressure, \f$P_{ref}\f$. - */ - void DebyeHuckel:: - getEnthalpy_RT(doublereal* hrt) const { - _updateStandardStateThermo(); - getEnthalpy_RT_ref(hrt); - doublereal pref; - doublereal delta_p; - double RT = _RT(); - for (int k = 0; k < m_kk; k++) { - pref = m_spthermo->refPressure(k); - delta_p = m_Pcurrent - pref; - hrt[k] += delta_p/ RT * m_speciesSize[k]; - } - if (m_waterSS) { - hrt[0] = m_waterSS->enthalpy_mole(); - hrt[0] /= RT; - } - } - - /* - * Get the nondimensional Entropies for the species - * standard states at the current T and P of the solution. - * - * Note, this is equal to the reference state entropies - * due to the zero volume expansivity: - * i.e., (dS/dp)_T = (dV/dT)_P = 0.0 - * - * The solvent water entropy is obtained from a pure water - * equation of state model. - * - * @param sr Vector of length m_kk, which on return sr[k] - * will contain the nondimensional - * standard state entropy of species k. - */ - void DebyeHuckel:: - getEntropy_R(doublereal* sr) const { - _updateStandardStateThermo(); - getEntropy_R_ref(sr); - if (m_waterSS) { - sr[0] = m_waterSS->entropy_mole(); - sr[0] /= GasConstant; - } - } - - /* - * Get the nondimensional heat capacity at constant pressure - * function for the species - * standard states at the current T and P of the solution. - * \f[ - * Cp^0_k(T,P) = Cp^{ref}_k(T) - * \f] - * where \f$V_k\f$ is the molar volume of pure species k. - * \f$ Cp^{ref}_k(T)\f$ is the constant pressure heat capacity - * of species k at the reference pressure, \f$p_{ref}\f$. - * - * The solvent water heat capacity is obtained from a pure water - * equation of state model. - * - * @param cpr Vector of length m_kk, which on return cpr[k] - * will contain the nondimensional - * constant pressure heat capacity for species k. - */ - void DebyeHuckel::getCp_R(doublereal* cpr) const { - _updateStandardStateThermo(); - getCp_R_ref(cpr); - if (m_waterSS) { - cpr[0] = m_waterSS->cp_mole(); - cpr[0] /= GasConstant; - } - } - - /* - * Get the molar volumes of each species in their standard - * states at the current - * T and P of the solution. - * units = m^3 / kmol - */ - void DebyeHuckel::getStandardVolumes(doublereal *vol) const { - _updateStandardStateThermo(); - copy(m_speciesSize.begin(), - m_speciesSize.end(), vol); - if (m_waterSS) { - double dd = m_waterSS->density(); - vol[0] = molecularWeight(0)/dd; - } - } - - void DebyeHuckel::getGibbs_RT_ref(doublereal *grt) const { - /* - * 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); - - if (m_waterSS) { - double pnow = m_Pcurrent; - double tnow = temperature(); - m_waterSS->setTempPressure(tnow, m_p0); - double mu0 = m_waterSS->gibbs_mole(); - m_waterSS->setTempPressure(tnow, pnow); - double rt = _RT(); - grt[0] = mu0 / rt; - } - - } - - void DebyeHuckel::getEnthalpy_RT_ref(doublereal *hrt) const { - /* - * 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_h0_RT.begin(), m_h0_RT.end(), hrt); - - if (m_waterSS) { - double pnow = m_Pcurrent; - double tnow = temperature(); - m_waterSS->setTempPressure(tnow, m_p0); - double h0 = m_waterSS->enthalpy_mole(); - m_waterSS->setTempPressure(tnow, pnow); - double rt = _RT(); - hrt[0] = h0 / rt; - } - } - - void DebyeHuckel::getEntropy_R_ref(doublereal *sr) const { - /* - * 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(), sr); - - if (m_waterSS) { - double pnow = m_Pcurrent; - double tnow = temperature(); - m_waterSS->setTempPressure(tnow, m_p0); - double s0 = m_waterSS->entropy_mole(); - m_waterSS->setTempPressure(tnow, pnow); - sr[0] = s0 / GasConstant; - } - } - - void DebyeHuckel::getCp_R_ref(doublereal *cpr) const { - /* - * 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(m_cp0_R.begin(), m_cp0_R.end(), cpr); - if (m_waterSS) { - double pnow = m_Pcurrent; - double tnow = temperature(); - m_waterSS->setTempPressure(tnow, m_p0); - double cp0 = m_waterSS->cp_mole(); - m_waterSS->setTempPressure(tnow, pnow); - cpr[0] = cp0 / GasConstant; - } - } - - /* - * Get the molar volumes of each species in their reference - * states at the current - * T and P of the solution. - * units = m^3 / kmol - */ - void DebyeHuckel::getStandardVolumes_ref(doublereal *vol) const { - double psave = m_Pcurrent; - _updateStandardStateThermo(m_p0); - copy(m_speciesSize.begin(), - m_speciesSize.end(), vol); - if (m_waterSS) { - double dd = m_waterSS->density(); - vol[0] = molecularWeight(0)/dd; - } - _updateStandardStateThermo(psave); - } - - /* - * ------ Thermodynamic Values for the Species Reference States --- - */ - - // -> This is handled by VPStandardStatesTP - /* * -------------- Utilities ------------------------------- */ @@ -1535,8 +1242,11 @@ namespace Cantera { /* * Initialize the water standard state model */ - if (m_waterSS) delete m_waterSS; - m_waterSS = new WaterPDSS(this, 0); + m_waterSS = dynamic_cast(providePDSS(0)) ; + if (!m_waterSS) { + throw CanteraError("HMWSoln::installThermoXML", + "Dynamic cast to PDSS_Water failed"); + } /* * Fill in the molar volume of water (m3/kmol) * at standard conditions to fill in the m_speciesSize entry @@ -1889,10 +1599,7 @@ namespace Cantera { } - if (m_waterSS) { - m_useTmpRefStateStorage = false; - } - + /* * Lastly set the state */ @@ -2904,19 +2611,15 @@ namespace Cantera { * thus the ss thermodynamics functions for all of the species * must be recalculated. */ - void DebyeHuckel::_updateStandardStateThermo(doublereal pnow) const { - _updateRefStateThermo(); - doublereal tnow = temperature(); - if (pnow == -1.0) { - pnow = m_Pcurrent; - } - if (m_tlast != tnow || m_plast != pnow) { - if (m_waterSS) { - m_waterSS->setTempPressure(tnow, pnow); - } - m_tlast = tnow; - m_plast = pnow; - } - } + // void DebyeHuckel::_updateStandardStateThermo() const { + // doublereal tnow = temperature(); + // doublereal pnow = m_Pcurrent; + // if (m_waterSS) { + // m_waterSS->setTempPressure(tnow, pnow); + // } + // m_VPSS_ptr->setState_TP(tnow, pnow); + // VPStandardStateTP::updateStandardStateThermo(); + + //} } diff --git a/Cantera/src/thermo/DebyeHuckel.h b/Cantera/src/thermo/DebyeHuckel.h index 7306fa1cf..12f0980d2 100644 --- a/Cantera/src/thermo/DebyeHuckel.h +++ b/Cantera/src/thermo/DebyeHuckel.h @@ -46,7 +46,7 @@ namespace Cantera { //@} class WaterProps; - class WaterPDSS; + class PDSS_Water; /** * @ingroup thermoprops @@ -1084,194 +1084,6 @@ namespace Cantera { //@} - /// @name Properties of the Standard State of the Species - // in the Solution -- - //@{ - - - - //! Get the array of chemical potentials at unit activity for the species - //! at their standard states at the current T and P of the solution. - /*! - * 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 - * - * Get the standard state chemical potentials of the species. - * This is the array of chemical potentials at unit activity - * \f$ \mu^0_k(T,P) \f$. - * Activity is molality based in this object. - * We define these here as the chemical potentials of the pure - * species at the temperature and pressure of the solution. - * This function is used in the evaluation of the - * equilibrium constant Kc. Therefore, Kc will also depend - * on T and P. This is the norm for liquid and solid systems. - * - * @param mu Output vector of chemical potentials. - * Length: m_kk. - */ - virtual void getStandardChemPotentials(doublereal* mu) const; - - //! Get the nondimensional Gibbs functions for the species - //! in their standard states at the current T and P of the solution. - /*! - * The standard states are on the unit molality basis. - * \f[ - * \mu^{\triangle}_k(T,P) = \mu^{\triangle,ref}_k(T) + (P - P_{ref}) * V_k - * \f] - * - * where \f$V_k\f$ is the molar volume of pure species k. - * \f$ \mu^{\triangle,ref}_k(T)\f$ is the chemical potential of pure - * species k at the reference pressure, \f$P_{ref}\f$. - * - * @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 T and P of the solution - /*! - * The standard states are on the unit molality basis. - * Units are Joules/kmol - * @param gpure Output vector of standard state gibbs free energies - * Length: m_kk. - */ - virtual void getPureGibbs(doublereal* gpure) const; - - //! Get the nondimensional Enthalpy functions for the species - //! at their standard states at the current T and P of the solution. - /*! - * The standard states are on the unit molality basis. - * We assume an incompressible constant partial molar - * volume for the solutes. - * - * \f[ - * h^{\triangle}_k(T,P) = h^{\triangle,ref}_k(T) + (P - P_{ref}) * V_k - * \f] - * - * where \f$V_k\f$ is the molar volume of SS species k. - * \f$ h^{ref}_k(T)\f$ is the enthalpy of the SS - * species k at the reference pressure, \f$P_{ref}\f$. - * - * The solvent water enthalpy is obtained from a pure water - * equation of state model. - * - * @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 - //! standard state species at the current T and P of the solution. - /*! - * - * The standard states are on the unit molality basis. - * - * \f[ - * s^{\triangle}_k(T,P) = s^{\triangle,ref}_k(T) - * \f] - * - * Note, this is equal to the reference state entropies - * due to the zero volume expansivity: - * i.e., (dS/dp)_T = (dV/dT)_P = 0.0 - * - * The solvent water entropy is obtained from a pure water - * equation of state model. - * - * @param sr Output vector of nondimensional standard state entropies. - * Length: m_kk. The solvent water is species 0, always. - */ - virtual void getEntropy_R(doublereal* sr) const; - - //! Get the nondimensional Heat Capacities at constant - //! pressure for the species standard states - //! at the current T and P of the solution - /*! - * The standard states are on the unit molality basis. - * For the solutes: - * \f[ - * Cp^\triangle_k(T,P) = Cp^{\triangle,ref}_k(T) - * \f] - * - * \f$ Cp^{ref}_k(T)\f$ is the constant pressure heat capacity - * of species k at the reference pressure, \f$p_{ref}\f$. - * - * The solute heat capacity is obtained from a pure water - * equation of state model, so it depends on T and P. - * - * @param cpr Vector of length m_kk, which on return cpr[k] - * will contain the nondimensional - * constant pressure heat capacity for species k. - */ - virtual void getCp_R(doublereal* cpr) const; - - //! Get the molar volumes of the species standard states at the current - //! T and P of the solution. - /*! - * The current model assumes that an incompressible molar volume for - * all solutes. The molar volume for the water solvent, however, - * is obtained from a pure water equation of state, waterSS. - * Therefore, the water standard state varies with both T and P. - * It is an error to request the water molar volume at a T and P - * where the water phase is not stable phase. - * - * units = m^3 / kmol - * - * @param vol Output vector containing the standard state volumes. - * Length: m_kk. The solvent water is species 0, always. - */ - virtual void getStandardVolumes(doublereal *vol) 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 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 - * 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 - * 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 reference states at the current - //! T and P_ref 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; protected: @@ -1286,7 +1098,7 @@ namespace Cantera { * @param pres Pressure at which to evaluate the standard states. * The default, indicated by a -1.0, is to use the current pressure */ - virtual void _updateStandardStateThermo(doublereal pres = -1.0) const; + //virtual void _updateStandardStateThermo() const; //@} /// @name Thermodynamic Values for the Species Reference States --- @@ -1865,7 +1677,7 @@ namespace Cantera { /*! * derived from the equation of state for water. */ - WaterPDSS *m_waterSS; + PDSS_Water *m_waterSS; //! Storage for the density of water's standard state /*! diff --git a/Cantera/src/thermo/GeneralSpeciesThermo.cpp b/Cantera/src/thermo/GeneralSpeciesThermo.cpp index bc41dab46..0a9471da8 100644 --- a/Cantera/src/thermo/GeneralSpeciesThermo.cpp +++ b/Cantera/src/thermo/GeneralSpeciesThermo.cpp @@ -186,6 +186,10 @@ namespace Cantera { * Resize the arrays if necessary, filling the empty * slots with the zero pointer. */ + if (!stit_ptr) { + throw CanteraError("GeneralSpeciesThermo::install_STIT", + "zero pointer"); + } int index = stit_ptr->speciesIndex(); if (index > m_kk - 1) { m_sp.resize(index+1, 0); @@ -208,68 +212,76 @@ namespace Cantera { 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 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]; + if (sp_ptr) { + 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::const_iterator _begin, _end; - _begin = m_sp.begin(); - _end = m_sp.end(); - SpeciesThermoInterpType * sp_ptr = 0; - for (; _begin != _end; ++_begin) { - sp_ptr = *(_begin); - if (sp_ptr) { - - sp_ptr->updatePropertiesTemp(t, cp_R, h_RT, s_R); - } - else { - writelog("General::update: sp_ptr is NULL!"); - } - } + /** + * Update the properties for all species. + */ + void GeneralSpeciesThermo:: + update(doublereal t, doublereal* cp_R, + doublereal* h_RT, doublereal* s_R) const { + vector::const_iterator _begin, _end; + _begin = m_sp.begin(); + _end = m_sp.end(); + SpeciesThermoInterpType * sp_ptr = 0; + for (; _begin != _end; ++_begin) { + sp_ptr = *(_begin); + if (sp_ptr) { + sp_ptr->updatePropertiesTemp(t, cp_R, h_RT, s_R); + } + // else { + // writelog("General::update: sp_ptr is NULL!\n"); + //} } + } - /** - * 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 the type of parameterization + * used for the species, index. + */ + int GeneralSpeciesThermo::reportType(int index) const { + SpeciesThermoInterpType *sp = m_sp[index]; + if (sp) { + return sp->reportType(); } + return -1; + } - /** - * 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"); - } + /** + * 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; + if (sp) { + sp->reportParameters(n, type, minTemp, maxTemp, + refPressure, c); + if (n != index) { + throw CanteraError(" ", "confused"); + } + } else { + type = -1; } + } //! Modify parameters for the standard state /*! @@ -280,43 +292,54 @@ namespace Cantera { void GeneralSpeciesThermo:: modifyParams(int index, doublereal *c) { SpeciesThermoInterpType *sp = m_sp[index]; - sp->modifyParameters(c); + if (sp) { + 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(); - } + /** + * 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]; + if (sp) { + return sp->minTemp(); + } } + return m_tlow_max; + } - doublereal GeneralSpeciesThermo::maxTemp(int k) const { - if (k < 0) { - return m_thigh_min; - } else { - SpeciesThermoInterpType *sp = m_sp[k]; - return sp->maxTemp(); - } + doublereal GeneralSpeciesThermo::maxTemp(int k) const { + if (k < 0) { + return m_thigh_min; + } else { + SpeciesThermoInterpType *sp = m_sp[k]; + if (sp) { + return sp->maxTemp(); + } } + return m_thigh_min; + } - doublereal GeneralSpeciesThermo::refPressure(int k) const { - if (k < 0) { - return m_p0; - } else { - SpeciesThermoInterpType *sp = m_sp[k]; - return sp->refPressure(); - } + doublereal GeneralSpeciesThermo::refPressure(int k) const { + if (k < 0) { + return m_p0; + } else { + SpeciesThermoInterpType *sp = m_sp[k]; + if (sp) { + return sp->refPressure(); + } } + return m_p0; + } } diff --git a/Cantera/src/thermo/GeneralSpeciesThermo.h b/Cantera/src/thermo/GeneralSpeciesThermo.h index f1d7ee8ae..b8a7505f9 100644 --- a/Cantera/src/thermo/GeneralSpeciesThermo.h +++ b/Cantera/src/thermo/GeneralSpeciesThermo.h @@ -209,8 +209,12 @@ namespace Cantera { * a list of pointers to type SpeciesThermoInterpType. * Note, this object owns the objects, so they are deleted * in the destructor of this object. + * Note, that in some instances, m_sp[k] = 0, e.g., no + * SpeciesThermoInterpType is installed for one or more + * species. These cases must be handled by the calling + * routine. */ - std::vector m_sp; + std::vector m_sp; //! Maximum value of the lowest temperature doublereal m_tlow_max; diff --git a/Cantera/src/thermo/HMWSoln.cpp b/Cantera/src/thermo/HMWSoln.cpp index 901e7aa3a..e6c42f566 100644 --- a/Cantera/src/thermo/HMWSoln.cpp +++ b/Cantera/src/thermo/HMWSoln.cpp @@ -28,7 +28,7 @@ #include "HMWSoln.h" #include "ThermoFactory.h" #include "WaterProps.h" -#include "WaterPDSS.h" +#include "PDSS_Water.h" #include namespace Cantera { @@ -164,21 +164,23 @@ namespace Cantera { m_IionicMolalityStoich= b.m_IionicMolalityStoich; m_form_A_Debye = b.m_form_A_Debye; m_A_Debye = b.m_A_Debye; - if (m_waterSS) { - delete m_waterSS; - m_waterSS = 0; - } - if (b.m_waterSS) { - m_waterSS = new WaterPDSS(*(b.m_waterSS)); + + // This is an internal shallow copy of the PDSS_Water pointer + m_waterSS = dynamic_cast(providePDSS(0)) ; + if (!m_waterSS) { + throw CanteraError("HMWSoln::operator=()", "Dynamic cast to PDSS_Water failed"); } + m_densWaterSS = b.m_densWaterSS; + if (m_waterProps) { delete m_waterProps; m_waterProps = 0; } if (b.m_waterProps) { - m_waterProps = new WaterProps(*(b.m_waterProps)); + m_waterProps = new WaterProps(m_waterSS); } + m_expg0_RT = b.m_expg0_RT; m_pe = b.m_pe; m_pp = b.m_pp; @@ -396,9 +398,6 @@ namespace Cantera { if (m_waterProps) { delete m_waterProps; m_waterProps = 0; } - if (m_waterSS) { - delete m_waterSS; m_waterSS = 0; - } } /** @@ -586,7 +585,7 @@ namespace Cantera { * update the standard state thermo * -> This involves calling the water function and setting the pressure */ - _updateStandardStateThermo(); + updateStandardStateThermo(); /* * Store the internal density of the water SS. @@ -598,34 +597,19 @@ namespace Cantera { * Calculate all of the other standard volumes * -> note these are constant for now */ - /* - * Get the partial molar volumes of all of the - * species. -> note this is a lookup for - * water, here since it was done above. - */ + calcDensity(); + } + + void HMWSoln::calcDensity() { double *vbar = &m_pp[0]; getPartialMolarVolumes(vbar); - - /* - * Get mole fractions of all species. - */ double *x = &m_tmpV[0]; getMoleFractions(x); - - /* - * Calculate the solution molar volume and the - * solution density. - */ doublereal vtotal = 0.0; for (int i = 0; i < m_kk; i++) { vtotal += vbar[i] * x[i]; } doublereal dd = meanMolecularWeight() / vtotal; - - /* - * Now, update the State class with the results. This - * store the denisty. - */ State::setDensity(dd); } @@ -661,7 +645,12 @@ namespace Cantera { "unimplemented"); return 0.0; } - + + double HMWSoln::density() const{ + // calcDensity(); + return State::density(); + } + /** * Overwritten setDensity() function is necessary because the * density is not an indendent variable. @@ -711,8 +700,10 @@ namespace Cantera { * the value propagates to underlying objects. */ void HMWSoln::setTemperature(doublereal temp) { - m_waterSS->setTemperature(temp); State::setTemperature(temp); + //m_waterSS->setTemperature(temp); + updateStandardStateThermo(); + calcDensity(); } // @@ -813,7 +804,7 @@ namespace Cantera { * */ void HMWSoln::getActivities(doublereal* ac) const { - _updateStandardStateThermo(); + updateStandardStateThermo(); /* * Update the molality array, m_molalities() * This requires an update due to mole fractions @@ -845,7 +836,7 @@ namespace Cantera { */ void HMWSoln:: getMolalityActivityCoefficients(doublereal* acMolality) const { - _updateStandardStateThermo(); + updateStandardStateThermo(); A_Debye_TP(-1.0, -1.0); s_update_lnMolalityActCoeff(); std::copy(m_lnActCoeffMolal.begin(), m_lnActCoeffMolal.end(), acMolality); @@ -1102,286 +1093,6 @@ namespace Cantera { } } - /* - * -------- Properties of the Standard State of the Species - * in the Solution ------------------ - */ - - /* - * getStandardChemPotentials() (virtual, const) - * - * - * Get the standard state chemical potentials of the species. - * This is the array of chemical potentials at unit activity - * (Mole fraction scale) - * \f$ \mu^0_k(T,P) \f$. - * We define these here as the chemical potentials of the pure - * species at the temperature and pressure of the solution. - * This function is used in the evaluation of the - * equilibrium constant Kc. Therefore, Kc will also depend - * on T and P. This is the norm for liquid and solid systems. - * - * units = J / kmol - */ - void HMWSoln::getStandardChemPotentials(doublereal* mu) const { - _updateStandardStateThermo(); - getGibbs_ref(mu); - doublereal pref; - doublereal delta_p; - for (int k = 1; k < m_kk; k++) { - pref = m_spthermo->refPressure(k); - delta_p = m_Pcurrent - pref; - mu[k] += delta_p * m_speciesSize[k]; - } - mu[0] = m_waterSS->gibbs_mole(); - } - - /* - * Get the nondimensional gibbs function for the species - * standard states at the current T and P of the solution. - * - * \f[ - * \mu^0_k(T,P) = \mu^{ref}_k(T) + (P - P_{ref}) * V_k - * \f] - * where \f$V_k\f$ is the molar volume of pure species k. - * \f$ \mu^{ref}_k(T)\f$ is the chemical potential of pure - * species k at the reference pressure, \f$P_{ref}\f$. - * - * @param grt Vector of length m_kk, which on return sr[k] - * will contain the nondimensional - * standard state gibbs function for species k. - */ - void HMWSoln::getGibbs_RT(doublereal* grt) const { - getStandardChemPotentials(grt); - doublereal invRT = 1.0 / _RT(); - for (int k = 0; k < m_kk; k++) { - grt[k] *= invRT; - } - } - - /* - * Get the Gibbs functions for the pure species - * at the current T and P of the solution. - * We assume an incompressible constant partial molar - * volume here: - * \f[ - * \mu^0_k(T,p) = \mu^{ref}_k(T) + (P - P_{ref}) * V_k - * \f] - * where \f$V_k\f$ is the molar volume of pure species k<\I>. - * \f$ u^{ref}_k(T)\f$ is the chemical potential of pure - * species k<\I> at the reference pressure, \f$P_{ref}\f$. - */ - void HMWSoln::getPureGibbs(doublereal* gpure) const { - getStandardChemPotentials(gpure); - } - - /* - * getEnthalpy_RT() (virtual, const) - * - * Get the array of nondimensional Enthalpy functions for the ss - * species at the current T and P of the solution. - * We assume an incompressible constant partial molar - * volume here: - * \f[ - * h^0_k(T,P) = h^{ref}_k(T) + (P - P_{ref}) * V_k - * \f] - * where \f$V_k\f$ is the molar volume of SS species k<\I>. - * \f$ h^{ref}_k(T)\f$ is the enthalpy of the SS - * species k<\I> at the reference pressure, \f$P_{ref}\f$. - */ - void HMWSoln:: - getEnthalpy_RT(doublereal* hrt) const { - /* - * Call the function that makes sure the local copy of - * the species reference thermo functions are up to date - * for the current temperature. - */ - _updateStandardStateThermo(); - /* - * Copy the gibbs function into return vector. - */ - std::copy(m_h0_RT.begin(), m_h0_RT.end(), hrt); - // We don't call the reference state functions, because there may - // not be a solution at 1 atm for the water equation. - // getEnthalpy_RT_ref(hrt); - doublereal pref; - doublereal delta_p; - double RT = _RT(); - for (int k = 1; k < m_kk; k++) { - pref = m_spthermo->refPressure(k); - delta_p = m_Pcurrent - pref; - hrt[k] += delta_p/ RT * m_speciesSize[k]; - } - hrt[0] = m_waterSS->enthalpy_mole(); - hrt[0] /= RT; - } - - /* - * getEntropy_R() (virtual, const) - * - * Get the nondimensional Entropies for the species - * standard states at the current T and P of the solution. - * - * Note, this is equal to the reference state entropies - * due to the zero volume expansivity: - * i.e., (dS/dp)_T = (dV/dT)_P = 0.0 - * - * @param sr Vector of length m_kk, which on return sr[k] - * will contain the nondimensional - * standard state entropy of species k. - */ - void HMWSoln:: - getEntropy_R(doublereal* sr) const { - _updateStandardStateThermo(); - /* - * Copy the gibbs function into return vector. - */ - std::copy(m_s0_R.begin(), m_s0_R.end(), sr); - // We don't call the reference state functions, because there may - // not be a solution at 1 atm for the water equation. - //getEntropy_R_ref(sr); - sr[0] = m_waterSS->entropy_mole(); - sr[0] /= GasConstant; - } - - /* - * Get the nondimensional heat capacity at constant pressure - * function for the species - * standard states at the current T and P of the solution. - * \f[ - * Cp^0_k(T,P) = Cp^{ref}_k(T) - * \f] - * where \f$V_k\f$ is the molar volume of pure species k. - * \f$ Cp^{ref}_k(T)\f$ is the constant pressure heat capacity - * of species k at the reference pressure, \f$p_{ref}\f$. - * - * @param cpr Vector of length m_kk, which on return cpr[k] - * will contain the nondimensional - * constant pressure heat capacity for species k. - */ - void HMWSoln::getCp_R(doublereal* cpr) const { - _updateStandardStateThermo(); - std::copy(m_cp0_R.begin(), m_cp0_R.end(), cpr); - //getCp_R_ref(cpr); - cpr[0] = m_waterSS->cp_mole(); - cpr[0] /= GasConstant; - } - - /* - * Get the molar volumes of each species in their standard - * states at the current - * T and P of the solution. - * units = m^3 / kmol - * - * The water calculation is done separately. - */ - void HMWSoln::getStandardVolumes(doublereal *vol) const { - _updateStandardStateThermo(); - std::copy(m_speciesSize.begin(), m_speciesSize.end(), vol); - double dd = m_waterSS->density(); - vol[0] = molecularWeight(0)/dd; - } - - - - void HMWSoln::getGibbs_RT_ref(doublereal *grt) const { - /* - * 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. - */ - std::copy(m_g0_RT.begin(), m_g0_RT.end(), grt); - - double pnow = m_Pcurrent; - double tnow = temperature(); - m_waterSS->setTempPressure(tnow, m_p0); - double mu0 = m_waterSS->gibbs_mole(); - m_waterSS->setTempPressure(tnow, pnow); - double rt = _RT(); - grt[0] = mu0 / rt; - } - - void HMWSoln::getEnthalpy_RT_ref(doublereal *hrt) const { - /* - * 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. - */ - std::copy(m_h0_RT.begin(), m_h0_RT.end(), hrt); - - double pnow = m_Pcurrent; - double tnow = temperature(); - m_waterSS->setTempPressure(tnow, m_p0); - double h0 = m_waterSS->enthalpy_mole(); - m_waterSS->setTempPressure(tnow, pnow); - double rt = _RT(); - hrt[0] = h0 / rt; - } - - - void HMWSoln::getEntropy_R_ref(doublereal *sr) const { - /* - * 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. - */ - std::copy(m_s0_R.begin(), m_s0_R.end(), sr); - - double pnow = m_Pcurrent; - double tnow = temperature(); - m_waterSS->setTempPressure(tnow, m_p0); - double s0 = m_waterSS->entropy_mole(); - m_waterSS->setTempPressure(tnow, pnow); - sr[0] = s0 / GasConstant; - } - - - void HMWSoln::getCp_R_ref(doublereal *cpr) const { - /* - * Call the function that makes sure the local copy of - * the species reference thermo functions are up to date - * for the current temperature. - */ - _updateRefStateThermo(); - std::copy(m_cp0_R.begin(), m_cp0_R.end(), cpr); - double pnow = m_Pcurrent; - double tnow = temperature(); - m_waterSS->setTempPressure(tnow, m_p0); - double cp0 = m_waterSS->cp_mole(); - m_waterSS->setTempPressure(tnow, pnow); - cpr[0] = cp0 / GasConstant; - } - - /* - * Get the molar volumes of each species in their reference - * states at the current - * T and P of the solution. - * units = m^3 / kmol - */ - void HMWSoln::getStandardVolumes_ref(doublereal *vol) const { - double psave = m_Pcurrent; - _updateStandardStateThermo(m_p0); - std::copy(m_speciesSize.begin(), - m_speciesSize.end(), vol); - if (m_waterSS) { - double dd = m_waterSS->density(); - vol[0] = molecularWeight(0)/dd; - } - _updateStandardStateThermo(psave); - } - /* * Updates the standard state thermodynamic functions at the current T and @@ -1394,20 +1105,15 @@ namespace Cantera { * thus the ss thermodynamics functions for all of the species * must be recalculated. */ - void HMWSoln::_updateStandardStateThermo(doublereal pnow) const { - _updateRefStateThermo(); - doublereal tnow = temperature(); - if (pnow == -1.0) { - pnow = m_Pcurrent; - } - if (m_tlast != tnow || m_plast != pnow) { - if (m_waterSS) { - m_waterSS->setTempPressure(tnow, pnow); - } - m_tlast = tnow; - m_plast = pnow; - } - } + // void HMWSoln::_updateStandardStateThermo() const { + //doublereal tnow = temperature(); + // doublereal pnow = m_Pcurrent; + // if (m_waterSS) { + // m_waterSS->setTempPressure(tnow, pnow); + // } + // m_VPSS_ptr->setState_TP(tnow, pnow); + // VPStandardStateTP::updateStandardStateThermo(); + //} /* * ------ Thermodynamic Values for the Species Reference States --- @@ -1730,6 +1436,7 @@ namespace Cantera { } + /** * initLengths(): * @@ -1739,7 +1446,6 @@ namespace Cantera { */ void HMWSoln::initLengths() { m_kk = nSpecies(); - MolalityVPSSTP::initThermo(); /* * Resize lengths equal to the number of species in diff --git a/Cantera/src/thermo/HMWSoln.h b/Cantera/src/thermo/HMWSoln.h index 7479b8ff2..44c9fa335 100644 --- a/Cantera/src/thermo/HMWSoln.h +++ b/Cantera/src/thermo/HMWSoln.h @@ -86,7 +86,7 @@ namespace Cantera { //@} class WaterProps; - class WaterPDSS; + class PDSS_Water; /** * Class %HMWSoln represents a dilute or concentrated liquid electrolyte @@ -1441,6 +1441,8 @@ namespace Cantera { */ void calcDensity(); + virtual doublereal density() const; + //! Set the internally storred density (gm/m^3) of the phase. /*! * Overwritten setDensity() function is necessary because of @@ -1752,203 +1754,8 @@ namespace Cantera { //@} - /// @name Properties of the Standard State of the Species - // in the Solution -- - //@{ - - - //! Get the array of chemical potentials at unit activity for the species - //! at their standard states at the current T and P - //! of the solution. - /*! - * 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 - * - * Get the standard state chemical potentials of the species. - * This is the array of chemical potentials at unit activity - * \f$ \mu^0_k(T,P) \f$. - * Activity is molality based in this object. - * We define these here as the chemical potentials of the pure - * species at the temperature and pressure of the solution. - * This function is used in the evaluation of the - * equilibrium constant Kc. Therefore, Kc will also depend - * on T and P. This is the norm for liquid and solid systems. - * - * units = J / kmol - * - * @param mu Output vector of chemical potentials. - * Length: m_kk. - */ - virtual void getStandardChemPotentials(doublereal* mu) const; - - - //! Get the nondimensional Gibbs functions for the species - //! in their standard states at the current T and P of the solution. - /*! - * The standard states of the solutes are on the unit molality basis. - * \f[ - * \mu^{\triangle}_k(T,P) = \mu^{\triangle,ref}_k(T) + (P - P_{ref}) * V_k - * \f] - * - * where \f$V_k\f$ is the molar volume of pure species k. - * \f$ \mu^{\triangle,ref}_k(T)\f$ is the chemical potential of pure - * species k at the reference pressure, \f$P_{ref}\f$. - * - * A real water model is used. Therefore, \f$ \mu^{o}_0(T,P) \f$ is a - * complicated function of temperature and pressure. - * - * @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 T and P of the solution - /*! - * The standard states are on the unit molality basis. - * Units are Joules/kmol - * @param gpure Output vector of standard state gibbs free energies - * Length: m_kk. - */ - virtual void getPureGibbs(doublereal* gpure) const; - - - //! Get the nondimensional Enthalpy functions for the species - //! at their standard states at the current T and P of the solution. - /*! - * The standard states are on the unit molality basis. - * We assume an incompressible constant partial molar - * volume for the solutes. - * - * \f[ - * h^{\triangle}_k(T,P) = h^{\triangle,ref}_k(T) + (P - P_{ref}) * V_k - * \f] - * - * where \f$V_k\f$ is the molar volume of SS species k. - * \f$ h^{ref}_k(T)\f$ is the enthalpy of the SS - * species k at the reference pressure, \f$P_{ref}\f$. - * - * The solvent water enthalpy is obtained from a pure water - * equation of state model. - * - * @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 - //! standard state species at the current T and P of the solution. - /*! - * - * The standard states are on the unit molality basis. - * - * \f[ - * s^{\triangle}_k(T,P) = s^{\triangle,ref}_k(T) - * \f] - * - * Note, this is equal to the reference state entropies - * due to the zero volume expansivity: - * i.e., (dS/dp)_T = (dV/dT)_P = 0.0 - * - * The solvent water entropy is obtained from a pure water - * equation of state model. - * - * @param sr Output vector of nondimensional standard state entropies. - * Length: m_kk. The solvent water is species 0, always. - */ - virtual void getEntropy_R(doublereal* sr) const; - - //! Get the nondimensional Heat Capacities at constant - //! pressure for the species standard states - //! at the current T and P of the solution - /*! - * The standard states are on the unit molality basis. - * For the solutes: - * \f[ - * Cp^\triangle_k(T,P) = Cp^{\triangle,ref}_k(T) - * \f] - * - * \f$ Cp^{ref}_k(T)\f$ is the constant pressure heat capacity - * of species k at the reference pressure, \f$p_{ref}\f$. - * - * The solute heat capacity is obtained from a pure water - * equation of state model, so it depends on T and P. - * - * @param cpr Vector of length m_kk, which on return cpr[k] - * will contain the nondimensional - * constant pressure heat capacity for species k. - */ - virtual void getCp_R(doublereal* cpr) const; - - - //! Get the molar volumes of the species standard states at the current - //! T and P of the solution. - /*! - * The current model assumes that an incompressible molar volume for - * all solutes. The molar volume for the water solvent, however, - * is obtained from a pure water equation of state, waterSS. - * Therefore, the water standard state varies with both T and P. - * It is an error to request the water molar volume at a T and P - * where the water phase is not stable phase. - * - * units = m^3 / kmol - * - * @param vol Output vector containing the standard state volumes. - * Length: m_kk. The solvent water is species 0, always. - */ - virtual void getStandardVolumes(doublereal *vol) 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 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 - * 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 - //! 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 reference states at the current - //! T and P_ref 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; - + + protected: //! Updates the standard state thermodynamic functions at the current T and P of the solution. @@ -1962,7 +1769,7 @@ namespace Cantera { * @param pres Pressure at which to evaluate the standard states. * The default, indicated by a -1.0, is to use the current pressure */ - virtual void _updateStandardStateThermo(doublereal pres = -1.0) const; + //virtual void _updateStandardStateThermo() const; //@} /// @name Thermodynamic Values for the Species Reference States --- @@ -2012,6 +1819,7 @@ namespace Cantera { * The length is equal to nElements(). */ virtual void setToEquilState(const doublereal* lambda_RT) { + updateStandardStateThermo(); err("setToEquilState"); } @@ -2534,7 +2342,7 @@ namespace Cantera { /*! * derived from the equation of state for water. */ - WaterPDSS *m_waterSS; + PDSS_Water *m_waterSS; //! density of standard-state water /*! diff --git a/Cantera/src/thermo/HMWSoln_input.cpp b/Cantera/src/thermo/HMWSoln_input.cpp index b7ca71fde..d198a3b65 100644 --- a/Cantera/src/thermo/HMWSoln_input.cpp +++ b/Cantera/src/thermo/HMWSoln_input.cpp @@ -19,7 +19,7 @@ #include "HMWSoln.h" #include "ThermoFactory.h" #include "WaterProps.h" -#include "WaterPDSS.h" +#include "PDSS_Water.h" #include using namespace std; @@ -947,10 +947,14 @@ namespace Cantera { if (modelString == "wateriapws" || modelString == "real_water" || modelString == "waterpdss") { /* - * Initialize the water standard state model + * Store a local pointer to the water standard state model. + * -> We've hardcoded it to a PDSS_Water model, so this is ok. */ - if (m_waterSS) delete m_waterSS; - m_waterSS = new WaterPDSS(this, 0); + m_waterSS = dynamic_cast(providePDSS(0)) ; + if (!m_waterSS) { + throw CanteraError("HMWSoln::initThermoXML", + "Dynamic cast to PDSS_Water failed"); + } /* * Fill in the molar volume of water (m3/kmol) * at standard conditions to fill in the m_speciesSize entry @@ -989,6 +993,7 @@ namespace Cantera { */ m_waterProps = new WaterProps(m_waterSS); + /* * Go get all of the coefficients and factors in the * activityCoefficients XML block @@ -1223,13 +1228,14 @@ namespace Cantera { } } + VPStandardStateTP::initThermoXML(phaseNode, id); /* * Lastly set the state */ - if (phaseNode.hasChild("state")) { - XML_Node& stateNode = phaseNode.child("state"); - setStateFromXML(stateNode); - } + // if (phaseNode.hasChild("state")) { + // XML_Node& stateNode = phaseNode.child("state"); + // setStateFromXML(stateNode); + //} } } diff --git a/Cantera/src/thermo/IdealGasPDSS.cpp b/Cantera/src/thermo/IdealGasPDSS.cpp deleted file mode 100644 index d010ad46b..000000000 --- a/Cantera/src/thermo/IdealGasPDSS.cpp +++ /dev/null @@ -1,379 +0,0 @@ -/** - * @file IdealGasPDSS.cpp - * - * Implementation of a pressure dependent standard state - * virtual function. - */ -/* - * Copywrite (2006) Sandia Corporation. Under the terms of - * Contract DE-AC04-94AL85000 with Sandia Corporation, the - * U.S. Government retains certain rights in this software. - */ -/* - * $Id$ - */ - -#include "ct_defs.h" -#include "xml.h" -#include "ctml.h" -#include "IdealGasPDSS.h" -//#include "importCTML.h" -#include "ThermoFactory.h" - -#include "ThermoPhase.h" - -using namespace std; - -namespace Cantera { - /** - * Basic list of constructors and duplicators - */ - - IdealGasPDSS::IdealGasPDSS(ThermoPhase *tp, int spindex) : - PDSS(tp, spindex) - { - constructPDSS(tp, spindex); - } - - - IdealGasPDSS::IdealGasPDSS(ThermoPhase *tp, int spindex, std::string inputFile, std::string id) : - PDSS(tp, spindex) - { - constructPDSSFile(tp, spindex, inputFile, id); - } - - - IdealGasPDSS::IdealGasPDSS(ThermoPhase *tp, int spindex, XML_Node& phaseRoot, std::string id) : - PDSS(tp, spindex) - { - constructPDSSXML(tp, spindex, phaseRoot, id) ; - } - - - IdealGasPDSS::IdealGasPDSS(const IdealGasPDSS &b) : - PDSS(b) - { - /* - * Use the assignment operator to do the brunt - * of the work for the copy construtor. - */ - *this = b; - } - - /** - * Assignment operator - */ - IdealGasPDSS& IdealGasPDSS::operator=(const IdealGasPDSS&b) { - if (&b == this) return *this; - PDSS::operator=(b); - return *this; - } - - IdealGasPDSS::~IdealGasPDSS() { - } - - //! Duplicator - ThermoPhase *IdealGasPDSS::duplMyselfAsThermoPhase() const { - IdealGasPDSS * idg = new IdealGasPDSS(*this); - return (ThermoPhase *) idg; - } - - void IdealGasPDSS::constructPDSS(ThermoPhase *tp, int spindex) { - initThermo(); - } - - - /** - * constructPDSSXML: - * - * Initialization of a IdealGasPDSS object using an - * xml file. - * - * This routine is a precursor to initThermo(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 IdealGasPDSS::constructPDSSXML(ThermoPhase *tp, int spindex, - XML_Node& phaseNode, std::string id) { - initThermo(); - } - - - /** - * constructPDSSFile(): - * - * Initialization of a IdealGasPDSS object using an - * xml file. - * - * This routine is a precursor to initThermo(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 IdealGasPDSS::constructPDSSFile(ThermoPhase *tp, int spindex, - std::string inputFile, std::string id) { - - if (inputFile.size() == 0) { - throw CanteraError("IdealGasPDSS::initThermo", - "input file is null"); - } - std::string path = findInputFile(inputFile); - ifstream fin(path.c_str()); - if (!fin) { - throw CanteraError("IdealGasPDSS::initThermo","could not open " - +path+" for reading."); - } - /* - * The phase object automatically constructs an XML object. - * Use this object to store information. - */ - - XML_Node *fxml = new XML_Node(); - fxml->build(fin); - XML_Node *fxml_phase = findXMLPhase(fxml, id); - if (!fxml_phase) { - throw CanteraError("IdealGasPDSS::initThermo", - "ERROR: Can not find phase named " + - id + " in file named " + inputFile); - } - constructPDSSXML(tp, spindex, *fxml_phase, id); - delete fxml; - } - - void IdealGasPDSS:: - initThermoXML(XML_Node& phaseNode, std::string id) { - initThermo(); - } - - void IdealGasPDSS::initThermo() { - } - - void IdealGasPDSS:: - setParametersFromXML(const XML_Node& eosdata) { - } - - /** - * Return the molar enthalpy in units of J kmol-1 - */ - doublereal IdealGasPDSS:: - enthalpy_mole() const { - throw CanteraError("IdealGasPDSS::enthalpy_mole()", "unimplemented"); - return (0.0); - } - - /** - * Calculate the internal energy in mks units of - * J kmol-1 - */ - doublereal IdealGasPDSS:: - intEnergy_mole() const { - throw CanteraError("IdealGasPDSS::enthalpy_mole()", "unimplemented"); - return (0.0); - } - - /** - * Calculate the entropy in mks units of - * J kmol-1 K-1 - */ - doublereal IdealGasPDSS:: - entropy_mole() const { - - throw CanteraError("IdealGasPDSS::entropy_mole()", "unimplemented"); - return (0.0); - } - - /** - * Calculate the Gibbs free energy in mks units of - * J kmol-1 K-1. - */ - doublereal IdealGasPDSS:: - gibbs_mole() const { - throw CanteraError("IdealGasPDSS::gibbs_mole()", "unimplemented"); - return (0.0); - } - - /** - * Calculate the constant pressure heat capacity - * in mks units of J kmol-1 K-1 - */ - doublereal IdealGasPDSS:: - cp_mole() const { - throw CanteraError("IdealGasPDSS::cp_mole()", "unimplemented"); - return (0.0); - } - - /** - * Calculate the constant volume heat capacity - * in mks units of J kmol-1 K-1 - */ - doublereal IdealGasPDSS:: - cv_mole() const { - throw CanteraError("IdealGasPDSS::cv_mole()", "unimplemented"); - return (0.0); - } - - - /** - * Return the difference in enthalpy between current p - * and ref p0, in mks units of - * in units of J kmol-1 - */ - doublereal IdealGasPDSS:: - enthalpyDelp_mole() const { - throw CanteraError("IdealGasPDSS::enthalpy_mole()", "unimplemented"); - return (0.0); - } - - /** - * Calculate difference in the internal energy between current p - * and ref p0, in mks units of - * J kmol-1 - */ - doublereal IdealGasPDSS:: - intEnergyDelp_mole() const { - throw CanteraError("IdealGasPDSS::enthalpyDelp_mole()", "unimplemented"); - return (0.0); - } - - /** - * Return the difference in entropy between current p - * and ref p0, in mks units of - * J kmol-1 K-1 - */ - doublereal IdealGasPDSS:: - entropyDelp_mole() const { - - throw CanteraError("IdealGasPDSS::entropyDelp_mole()", "unimplemented"); - return (0.0); - } - - /** - * Calculate the difference in Gibbs free energy between current p and - * the ref p0, in mks units of - * J kmol-1 K-1. - */ - doublereal IdealGasPDSS:: - gibbsDelp_mole() const { - throw CanteraError("IdealGasPDSS::gibbsDelp_mole()", "unimplemented"); - return (0.0); - } - - /** - * Calculate the difference in the constant pressure heat capacity - * between the current p and the ref p0, - * in mks units of J kmol-1 K-1 - */ - doublereal IdealGasPDSS:: - cpDelp_mole() const { - throw CanteraError("IdealGasPDSS::cpDelp_mole()", "unimplemented"); - return (0.0); - } - - /** - * Calculate the difference in constant volume heat capacity - * between the current p and the ref p0 - * in mks units of J kmol-1 K-1 - */ - doublereal IdealGasPDSS:: - cvDelp_mole() const { - throw CanteraError("IdealGasPDSS::cvDelp_mole()", "unimplemented"); - return (0.0); - } - - /** - * Calculate the pressure (Pascals), given the temperature and density - * Temperature: kelvin - * rho: density in kg m-3 - */ - doublereal IdealGasPDSS:: - pressure() const { - throw CanteraError("IdealGasPDSS::pressure()", "unimplemented"); - return (0.0); - } - - void IdealGasPDSS:: - setPressure(doublereal p) { - throw CanteraError("IdealGasPDSS::pressure()", "unimplemented"); - } - - - /// critical temperature - doublereal IdealGasPDSS::critTemperature() const { - throw CanteraError("IdealGasPDSS::critTemperature()", "unimplemented"); - return (0.0); - } - - /// critical pressure - doublereal IdealGasPDSS::critPressure() const { - throw CanteraError("IdealGasPDSS::critPressure()", "unimplemented"); - return (0.0); - } - - /// critical density - doublereal IdealGasPDSS::critDensity() const { - throw CanteraError("IdealGasPDSS::critDensity()", "unimplemented"); - return (0.0); - } - - void IdealGasPDSS::setDensity(double dens) { - m_dens = dens; - } - - /** - * Return the density of the standard state - * - * We assume that the storred density is current. - * Note, this is the density of the standard state, - * not of the mixture. - */ - double IdealGasPDSS::density() const { - return m_dens; - } - - /** - * Return the temperature - * - * Obtain the temperature from the owning ThermoPhase object - * if you can. - */ - double IdealGasPDSS::temperature() const { - if (m_tp) { - m_temp = m_tp->temperature(); - } - return m_temp; - } - - void IdealGasPDSS::setTemperature(double temp) { - m_temp = temp; - } - - doublereal IdealGasPDSS::molecularWeight() const { - return m_mw; - } - void IdealGasPDSS::setMolecularWeight(double mw) { - m_mw = mw; - } - - void IdealGasPDSS::setState_TP(double temp, double pres) { - throw CanteraError("IdealGasPDSS::setState_TP()", "unimplemented"); - } - - /// saturation pressure - doublereal IdealGasPDSS::satPressure(doublereal t){ - throw CanteraError("IdealGasPDSS::satPressure()", "unimplemented"); - return (0.0); - } - - -} diff --git a/Cantera/src/thermo/IdealGasPDSS.h b/Cantera/src/thermo/IdealGasPDSS.h deleted file mode 100644 index dbbcd1122..000000000 --- a/Cantera/src/thermo/IdealGasPDSS.h +++ /dev/null @@ -1,164 +0,0 @@ -/** - * @file IDEALGASPDSS.h - * - * Declares class PDSS pressure dependent standard state - * for a single species - */ -/* - * Copywrite (2006) Sandia Corporation. Under the terms of - * Contract DE-AC04-94AL85000 with Sandia Corporation, the - * U.S. Government retains certain rights in this software. - */ -/* - * $Id$ - */ - -#ifndef CT_IDEALGASPDSS_H -#define CT_IDEALGASPDSS_H - -#include "PDSS.h" - -class XML_Node; -class ThermoPhase; - -namespace Cantera { - - - /** - * Class for pressure dependent standard states. - * This class is for a single Ideal Gas species. - * - */ - class IdealGasPDSS : public PDSS { - - public: - - /** - * Basic list of constructors and duplicators - */ - IdealGasPDSS(ThermoPhase *tp, int spindex); - - //! Copy Constructur - /*! - * @param b Object to be copied - */ - IdealGasPDSS(const IdealGasPDSS &b); - - //! Assignment operator - /*! - * @param b Object to be copeid - */ - IdealGasPDSS& operator=(const IdealGasPDSS&b); - - IdealGasPDSS(ThermoPhase *tp, int spindex, - std::string inputFile, std::string id = ""); - IdealGasPDSS(ThermoPhase *tp, int spindex, XML_Node& phaseRef, - std::string id = ""); - - //! Destructor - virtual ~IdealGasPDSS(); - - //! Duplicator - virtual ThermoPhase *duplMyselfAsThermoPhase() const; - - /** - * - * @name Utilities - * @{ - */ - virtual int pdssType() const { return -1; } - - /** - * @} - * @name Molar Thermodynamic Properties of the Solution -------------- - * @{ - */ - 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; - - /* - * Get the difference in the standard state thermodynamic properties - * between the reference pressure, po, and the current pressure. - */ - virtual doublereal enthalpyDelp_mole() const; - virtual doublereal intEnergyDelp_mole() const; - virtual doublereal entropyDelp_mole() const; - virtual doublereal gibbsDelp_mole() const; - virtual doublereal cpDelp_mole() const; - virtual doublereal cvDelp_mole() const; - - //@} - /// @name Mechanical Equation of State Properties --------------------- - //@{ - - virtual doublereal pressure() const; - virtual void setPressure(doublereal p); - - //@} - /// @name Partial Molar Properties of the Solution ----------------- - //@{ - - virtual void getChemPotentials(doublereal* mu) const { - mu[0] = gibbs_mole(); - } - - //@} - /// @name Properties of the Standard State of the Species - // in the Solution -- - //@{ - - - /// critical temperature - virtual doublereal critTemperature() const; - - /// critical pressure - virtual doublereal critPressure() const; - - /// critical density - virtual doublereal critDensity() const; - - /// saturation temperature - //virtual doublereal satTemperature(doublereal p) const; - - - - /// saturation pressure - virtual doublereal satPressure(doublereal t); - - virtual void setDensity(double dens); - double density() const; - virtual void setTemperature(double temp); - double temperature() const; - virtual void setState_TP(double temp, double pres); - - doublereal molecularWeight() const; - void setMolecularWeight(double mw); - - virtual void constructPDSS(ThermoPhase *tp, int spindex); - virtual void constructPDSSFile(ThermoPhase *tp, int spindex, - std::string inputFile, std::string id); - virtual void constructPDSSXML(ThermoPhase *tp, int spindex, - XML_Node& phaseNode, std::string id); - virtual void initThermoXML(XML_Node& eosdata, std::string id); - virtual void initThermo(); - virtual void setParametersFromXML(const XML_Node& eosdata); - - protected: - - int m_kk, m_mm; - doublereal m_tmin, m_tmax, m_p0; - - - - }; - -} - -#endif - - - diff --git a/Cantera/src/thermo/IdealGasPhase.cpp b/Cantera/src/thermo/IdealGasPhase.cpp index 7f3ac00f7..b442f540b 100644 --- a/Cantera/src/thermo/IdealGasPhase.cpp +++ b/Cantera/src/thermo/IdealGasPhase.cpp @@ -441,24 +441,24 @@ namespace Cantera { // new methods defined here ------------------------------- - void IdealGasPhase::initThermo() { + 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(); + 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); - } + 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 diff --git a/Cantera/src/thermo/IdealMolalSoln.cpp b/Cantera/src/thermo/IdealMolalSoln.cpp index 6a98971a6..5c1f37da0 100644 --- a/Cantera/src/thermo/IdealMolalSoln.cpp +++ b/Cantera/src/thermo/IdealMolalSoln.cpp @@ -38,7 +38,6 @@ namespace Cantera { MolalityVPSSTP(), m_formGC(2) { - m_useTmpRefStateStorage = true; } /** @@ -81,7 +80,6 @@ namespace Cantera { MolalityVPSSTP(), m_formGC(2) { - m_useTmpRefStateStorage = true; constructPhaseFile(inputFile, id); } @@ -89,7 +87,6 @@ namespace Cantera { MolalityVPSSTP(), m_formGC(2) { - m_useTmpRefStateStorage = true; constructPhaseXML(root, id); } @@ -216,14 +213,7 @@ namespace Cantera { // ------- Mechanical Equation of State Properties ------------------------ // - /* - * Pressure. Units: Pa. - * For this incompressible system, we return the internally storred - * independent value of the pressure. - */ - doublereal IdealMolalSoln::pressure() const { - return m_Pcurrent; - } + /* * Set the pressure at constant temperature. Units: Pa. @@ -244,7 +234,7 @@ namespace Cantera { * update the standard state thermo * -> This involves calling the water function and setting the pressure */ - _updateStandardStateThermo(); + updateStandardStateThermo(); /* * Calculate all of the other standard volumes @@ -608,8 +598,7 @@ namespace Cantera { * property manager. They are polynomial functions of temperature. * @see SpeciesThermo */ - void IdealMolalSoln:: - getPartialMolarEntropies(doublereal* sbar) const { + void IdealMolalSoln::getPartialMolarEntropies(doublereal* sbar) const { getEntropy_R(sbar); doublereal R = GasConstant; doublereal mm; @@ -670,190 +659,7 @@ namespace Cantera { * in the Solution ------------------ */ - /* - * Get the standard state chemical potentials of the species. - * This is the array of chemical potentials at unit activity - * (Mole fraction scale) - * \f$ \mu^0_k(T,P) \f$. - * We define these here as the chemical potentials of the pure - * species at the temperature and pressure of the solution. - * This function is used in the evaluation of the - * equilibrium constant Kc. Therefore, Kc will also depend - * on T and P. This is the norm for liquid and solid systems. - * - * units = J / kmol - */ - void IdealMolalSoln::getStandardChemPotentials(doublereal* mu) const { - _updateStandardStateThermo(); - getGibbs_ref(mu); - doublereal pref; - doublereal delta_p; - for (int k = 0; k < m_kk; k++) { - pref = m_spthermo->refPressure(k); - delta_p = m_Pcurrent - pref; - mu[k] += delta_p * m_speciesMolarVolume[k]; - } - } - - /* - * Get the nondimensional gibbs function for the species - * standard states at the current T and P of the solution. - * - * \f[ - * \mu^0_k(T,P) = \mu^{ref}_k(T) + (P - P_{ref}) * V_k - * \f] - * where \f$V_k\f$ is the molar volume of pure species k. - * \f$ \mu^{ref}_k(T)\f$ is the chemical potential of pure - * species k at the reference pressure, \f$P_{ref}\f$. - * - * @param grt Vector of length m_kk, which on return sr[k] - * will contain the nondimensional - * standard state gibbs function for species k. - */ - void IdealMolalSoln::getGibbs_RT(doublereal* grt) const { - getPureGibbs(grt); - doublereal invRT = 1.0 / _RT(); - for (int k = 0; k < m_kk; k++) { - grt[k] *= invRT; - } - } - - /* - * Get the Gibbs functions for the pure species - * at the current T and P of the solution. - * We assume an incompressible constant partial molar - * volume here: - * \f[ - * \mu^0_k(T,p) = \mu^{ref}_k(T) + (P - P_{ref}) * V_k - * \f] - * where \f$V_k\f$ is the molar volume of pure species k. - * \f$ u^{ref}_k(T)\f$ is the chemical potential of pure - * species k at the reference pressure, \f$P_{ref}\f$. - * - * Units: J/kmol - */ - void IdealMolalSoln::getPureGibbs(doublereal* gpure) const { - _updateStandardStateThermo(); - getGibbs_ref(gpure); - doublereal pref; - doublereal delta_p; - for (int k = 0; k < m_kk; k++) { - pref = m_spthermo->refPressure(k); - delta_p = m_Pcurrent - pref; - gpure[k] += delta_p * m_speciesMolarVolume[k]; - } - } - /* - * Get the array of nondimensional Enthalpy functions for the ss - * species at the current T and P of the solution. - * We assume an incompressible constant partial molar - * volume here: - * \f[ - * h^0_k(T,P) = h^{ref}_k(T) + (P - P_{ref}) * V_k - * \f] - * where \f$V_k\f$ is the molar volume of SS species k. - * \f$ h^{ref}_k(T)\f$ is the enthalpy of the SS - * species k at the reference pressure, \f$P_{ref}\f$. - * - * Units: dimensionless. - */ - void IdealMolalSoln:: - getEnthalpy_RT(doublereal* hrt) const { - _updateStandardStateThermo(); - getEnthalpy_RT_ref(hrt); - doublereal pref; - doublereal delta_p; - double RT = _RT(); - for (int k = 0; k < m_kk; k++) { - pref = m_spthermo->refPressure(k); - delta_p = m_Pcurrent - pref; - hrt[k] += delta_p/ RT * m_speciesMolarVolume[k]; - } - } - - /* - * Get the nondimensional Entropies for the species - * standard states: Units: J/kmol/K - * - * Note, this is equal to the reference state entropies - * due to the zero volume expansivity. - * i.e., (dS/dp)_T = (dV/dT)_P = 0.0 - * - * \f[ - * S^0_k(T,P) = S^{ref}_k(T) - * \f] - * - * Units: dimensionless - * - * @param sr Vector of length m_kk, which on return sr[k] - * will contain the nondimensional - * standard state entropy of species k. - */ - void IdealMolalSoln:: - getEntropy_R(doublereal* sr) const { - _updateStandardStateThermo(); - getEntropy_R_ref(sr); - } - - /* - * Get the nondimensional heat capacity at constant pressure - * function for the species - * standard states: Units J/kmol/K - * \f[ - * Cp^0_k(T,P) = Cp^{ref}_k(T) - * \f] - * where \f$V_k\f$ is the molar volume of pure species k. - * \f$ Cp^{ref}_k(T)\f$ is the constant pressure heat capacity - * of species k at the reference pressure, \f$p_{ref}\f$. - * - * @param cpr Vector of length m_kk, which on return cpr[k] - * will contain the nondimensional - * constant pressure heat capacity for species k. - */ - void IdealMolalSoln::getCp_R(doublereal* cpr) const { - _updateStandardStateThermo(); - getCp_R_ref(cpr); - } - - /* - * Get the molar volumes of each species in their standard - * states at the current - * T and P of the solution. - * - * \f[ - * V^0_k(T,P) = V^{ref}_k() - * \f] - - * Units = m^3 / kmol - */ - void IdealMolalSoln::getStandardVolumes(doublereal *vol) const { - _updateStandardStateThermo(); - std::copy(m_speciesMolarVolume.begin(), - m_speciesMolarVolume.end(), vol); - } - - /* - * Updates the standard state thermodynamic functions at the current T and P of the solution. - * - * @internal - * - * This function gets called for every call to functions in this - * class. It checks to see whether the temperature or pressure has changed and - * thus the ss thermodynamics functions for all of the species - * must be recalculated. - */ - void IdealMolalSoln::_updateStandardStateThermo(doublereal pnow) const { - _updateRefStateThermo(); - doublereal tnow = temperature(); - if (pnow == -1.0) { - pnow = m_Pcurrent; - } - if (m_tlast != tnow || m_plast != pnow) { - m_tlast = tnow; - m_plast = pnow; - } - } /* * ------ Thermodynamic Values for the Species Reference States --- @@ -1094,6 +900,7 @@ namespace Cantera { m_speciesMolarVolume[k] = getFloat(*ss, "molarVolume", "-"); } + MolalityVPSSTP::initThermoXML(phaseNode, id); /* * Set the state */ diff --git a/Cantera/src/thermo/IdealMolalSoln.h b/Cantera/src/thermo/IdealMolalSoln.h index e0761c942..0e6f0c467 100644 --- a/Cantera/src/thermo/IdealMolalSoln.h +++ b/Cantera/src/thermo/IdealMolalSoln.h @@ -243,12 +243,6 @@ namespace Cantera { */ - /*! - * Pressure. Units: Pa. - * For this incompressible system, we return the internally storred - * independent value of the pressure. - */ - virtual doublereal pressure() const; /** * Set the pressure at constant temperature. Units: Pa. @@ -615,146 +609,9 @@ namespace Cantera { // in the Solution -- //@{ - //! Get the standard state chemical potentials of the species. - /*! - * This is the array of chemical potentials at unit activity - * \f$ \mu^0_k(T,P) \f$. - * We define these here as the chemical potentials of the pure - * species at the temperature and pressure of the solution. - * This function is used in the evaluation of the - * equilibrium constant Kc. Therefore, Kc will also depend - * on T and P. This is the norm for liquid and solid systems. - * - * units = J / kmol - * - * @param mu Output vector of standard state chemical potentials. - * Length: m_kk. - */ - virtual void getStandardChemPotentials(doublereal* mu) const; - - /*! - * Get the nondimensional gibbs function for the species - * standard states at the current T and P of the solution. - * - * \f[ - * \mu^0_k(T,P) = \mu^{ref}_k(T) + (P - P_{ref}) * V_k - * \f] - * where \f$V_k\f$ is the molar volume of pure species k. - * \f$ \mu^{ref}_k(T)\f$ is the chemical potential of pure - * species k at the reference pressure, \f$P_{ref}\f$. - * - * @param grt Vector of length m_kk, which on return sr[k] - * will contain the nondimensional - * standard state gibbs function for species k. - */ - virtual void getGibbs_RT(doublereal* grt) const; - - - //! Get the Gibbs functions for the standard state species - //! at the current T and P of the solution. - /*! - * We assume an incompressible constant partial molar - * volume here: - * \f[ - * \mu^0_k(T,p) = \mu^{ref}_k(T) + (P - P_{ref}) * V_k - * \f] - * where \f$V_k\f$ is the molar volume of pure species k. - * \f$ u^{ref}_k(T)\f$ is the chemical potential of pure - * species k at the reference pressure, \f$P_{ref}\f$. - * - * Units: J/kmol - * - * @param gpure Output vector of standard state gibbs free energies. - * Length: m_kk. - */ - virtual void getPureGibbs(doublereal* gpure) const; - - //! Get the array of nondimensional Enthalpy functions for the ss - //! species at the current T and P of the solution. - /*! - * We assume an incompressible constant partial molar volume here: - * - * \f[ - * h^0_k(T,P) = h^{ref}_k(T) + (P - P_{ref}) * V_k - * \f] - * - * where \f$V_k\f$ is the molar volume of SS species k. - * \f$ h^{ref}_k(T)\f$ is the enthalpy of the SS - * species k at the reference pressure, \f$P_{ref}\f$. - * - * @param hrt Output vector of nondimensional standard state - * enthalpies. Length: m_kk. - */ - virtual void getEnthalpy_RT(doublereal* hrt) const; - - - //! Get the nondimensional Entropies for the species - //! standard states at the current T and P of the solution. - /*! - * - * Note, this is equal to the reference state entropies - * due to the zero volume expansivity: - * - * i.e., (dS/dp)_T = (dV/dT)_P = 0.0 - * - * \f[ - * S^0_k(T,P) = S^{ref}_k(T) - * \f] - * - * @param sr Vector of length m_kk, which on return sr[k] - * will contain the nondimensional - * standard state entropy of species k. - */ - virtual void getEntropy_R(doublereal* sr) const; - - - //! Get the nondimensional heat capacity at constant pressure - //! function for the species standard states at the current T and P of the solution. - /*! - * \f[ - * Cp^0_k(T,P) = Cp^{ref}_k(T) - * \f] - * where \f$V_k\f$ is the molar volume of pure species k. - * \f$ Cp^{ref}_k(T)\f$ is the constant pressure heat capacity - * of species k at the reference pressure, \f$p_{ref}\f$. - * - * @param cpr Vector of length m_kk, which on return cpr[k] - * will contain the nondimensional - * constant pressure heat capacity for species k. - */ - virtual void getCp_R(doublereal* cpr) const; - - //! Get the molar volumes of each species in their standard - //! states at the current T and P of the solution. - /*! - * - * \f[ - * V^0_k(T,P) = V^{ref}_k() - * \f] - * units = m^3 / kmol - * - * @param vol Output vector of standard state volumes. - * Length: m_kk. - */ - virtual void getStandardVolumes(doublereal *vol) const; - - //! Updates the standard state thermodynamic functions at the current T and P of the solution. - /*! - * @internal - * - * This function gets called for every call to functions in this - * class. It checks to see whether the temperature or pressure has changed and - * thus the ss thermodynamics functions for all of the species - * must be recalculated. - * - * Note, this function doesn't really do anything. I just left it in as a template - * for other situations which need a calculation at this level. - * - * @param pres Pressure at which to evaluate the standard states. - * The default, indicated by a -1.0, is to use the current pressure - */ - virtual void _updateStandardStateThermo(doublereal pres = -1.0) const; + + //@} /// @name Thermodynamic Values for the Species Reference States --- //@{ diff --git a/Cantera/src/thermo/IdealSolidSolnPhase.h b/Cantera/src/thermo/IdealSolidSolnPhase.h index 3f3edc537..34f04df06 100644 --- a/Cantera/src/thermo/IdealSolidSolnPhase.h +++ b/Cantera/src/thermo/IdealSolidSolnPhase.h @@ -25,7 +25,6 @@ #include "mix_defs.h" #include "ThermoPhase.h" -//#include "importCTML.h" #include "ThermoFactory.h" #include "SpeciesThermo.h" diff --git a/Cantera/src/thermo/IdealSolnGasVPSS.cpp b/Cantera/src/thermo/IdealSolnGasVPSS.cpp new file mode 100644 index 000000000..ee036439b --- /dev/null +++ b/Cantera/src/thermo/IdealSolnGasVPSS.cpp @@ -0,0 +1,530 @@ +/** + * @file IdealSolnGasVPSS.cpp + * Definition file for a derived class of ThermoPhase that assumes either + * an ideal gas or ideal solution approximation and handles + * variable pressure standard state methods for calculating + * thermodynamic properties (see \ref thermoprops and + * class \link Cantera::IdealSolnGasVPSS IdealSolnGasVPSS\endlink). + */ +/* + * 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 "IdealSolnGasVPSS.h" +#include "VPSSMgr.h" +#include "PDSS.h" +#include "mix_defs.h" +#include "ThermoFactory.h" + +using namespace std; + +namespace Cantera { + + /* + * Default constructor + */ + IdealSolnGasVPSS::IdealSolnGasVPSS() : + VPStandardStateTP(), + m_idealGas(0), + m_formGC(0) + { + } + + + IdealSolnGasVPSS::IdealSolnGasVPSS(std::string infile, std::string id) : + VPStandardStateTP(), + m_idealGas(0), + m_formGC(0) + { + XML_Node* root = get_XML_File(infile); + if (id == "-") id = ""; + XML_Node* xphase = get_XML_NameID("phase", std::string("#")+id, root); + if (!xphase) { + throw CanteraError("newPhase", + "Couldn't find phase named \"" + id + "\" in file, " + infile); + } + importPhase(*xphase, this); + } + + /* + * 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. + */ + IdealSolnGasVPSS::IdealSolnGasVPSS(const IdealSolnGasVPSS &b) : + VPStandardStateTP(), + m_idealGas(0), + m_formGC(0) + { + *this = b; + } + + /* + * operator=() + * + * Note this stuff will not work until the underlying phase + * has a working assignment operator + */ + IdealSolnGasVPSS& IdealSolnGasVPSS:: + operator=(const IdealSolnGasVPSS &b) { + if (&b != this) { + /* + * Mostly, this is a passthrough to the underlying + * assignment operator for the ThermoPhae parent object. + */ + VPStandardStateTP::operator=(b); + /* + * However, we have to handle data that we own. + */ + m_idealGas = b.m_idealGas; + m_formGC = b.m_formGC; + } + return *this; + } + + /* + * ~IdealSolnGasVPSS(): (virtual) + * + */ + IdealSolnGasVPSS::~IdealSolnGasVPSS() { + } + + /* + * Duplication function. + * This calls the copy constructor for this object. + */ + ThermoPhase* IdealSolnGasVPSS::duplMyselfAsThermoPhase() const { + IdealSolnGasVPSS* vptp = new IdealSolnGasVPSS(*this); + return (ThermoPhase *) vptp; + } + + int IdealSolnGasVPSS::eosType() const { + if (m_idealGas) { + return cIdealSolnGasVPSS; + } + return cIdealSolnGasVPSS_iscv; + } + + + /* + * ------------Molar Thermodynamic Properties ------------------------- + */ + + /// Molar enthalpy. Units: J/kmol. + doublereal IdealSolnGasVPSS::enthalpy_mole() const { + updateStandardStateThermo(); + const vector_fp &enth_RT = m_VPSS_ptr->enthalpy_RT(); + return (GasConstant * temperature() * + mean_X(DATA_PTR(enth_RT))); + } + + /// Molar internal energy. Units: J/kmol. + doublereal IdealSolnGasVPSS::intEnergy_mole() const { + doublereal p0 = pressure(); + doublereal md = molarDensity(); + return (enthalpy_mole() - p0 / md); + } + + /// Molar entropy. Units: J/kmol/K. + doublereal IdealSolnGasVPSS::entropy_mole() const { + updateStandardStateThermo(); + const vector_fp &entrop_R = m_VPSS_ptr->entropy_R(); + return GasConstant * (mean_X(DATA_PTR(entrop_R)) - sum_xlogx()); + + } + + /// Molar Gibbs function. Units: J/kmol. + doublereal IdealSolnGasVPSS::gibbs_mole() const { + return enthalpy_mole() - temperature() * entropy_mole(); + } + + /// Molar heat capacity at constant pressure. Units: J/kmol/K. + doublereal IdealSolnGasVPSS::cp_mole() const { + updateStandardStateThermo(); + const vector_fp &cp_R = m_VPSS_ptr->cp_R(); + return GasConstant * (mean_X(DATA_PTR(cp_R))); + } + + /// Molar heat capacity at constant volume. Units: J/kmol/K. + doublereal IdealSolnGasVPSS::cv_mole() const { + return cp_mole() - GasConstant; + + } + + void IdealSolnGasVPSS::setPressure(doublereal p) { + m_Pcurrent = p; + updateStandardStateThermo(); + calcDensity(); + } + + void IdealSolnGasVPSS::calcDensity() { + /* + * Calculate the molarVolume of the solution (m**3 kmol-1) + */ + if (m_idealGas) { + double dens = (m_Pcurrent * meanMolecularWeight() + /(GasConstant * temperature())); + State::setDensity(dens); + } else { + const doublereal * const dtmp = moleFractdivMMW(); + const vector_fp& vss = m_VPSS_ptr->standardVolumes(); + double invDens = dot(vss.begin(), vss.end(), dtmp); + /* + * Set the density in the parent State object directly, + * by calling the State::setDensity() function. + */ + double dens = 1.0/invDens; + State::setDensity(dens); + } + } + + doublereal IdealSolnGasVPSS::isothermalCompressibility() const { + if (m_idealGas) { + return -1.0 / m_Pcurrent; + } else { + throw CanteraError("IdealSolnGasVPSS::isothermalCompressibility() ", + "not implemented"); + } + return 0.0; + } + + void IdealSolnGasVPSS::getActivityConcentrations(doublereal* c) const { + if (m_idealGas) { + getConcentrations(c); + } else { + int k; + const vector_fp& vss = m_VPSS_ptr->standardVolumes(); + switch (m_formGC) { + case 0: + for (k = 0; k < m_kk; k++) { + c[k] = moleFraction(k); + } + break; + case 1: + for (k = 0; k < m_kk; k++) { + c[k] = moleFraction(k) / vss[k]; + } + break; + case 2: + for (k = 0; k < m_kk; k++) { + c[k] = moleFraction(k) / vss[0]; + } + break; + } + } + } + + /* + * Returns the standard concentration \f$ C^0_k \f$, which is used to normalize + * the generalized concentration. + */ + doublereal IdealSolnGasVPSS::standardConcentration(int k) const { + if (m_idealGas) { + double p = pressure(); + return p/(GasConstant * temperature()); + } else { + const vector_fp& vss = m_VPSS_ptr->standardVolumes(); + switch (m_formGC) { + case 0: + return 1.0; + break; + case 1: + return 1.0 / vss[k]; + break; + case 2: + return 1.0/ vss[0]; + break; + } + return 0.0; + + } + } + + /* + * Returns the natural logarithm of the standard + * concentration of the kth species + */ + doublereal IdealSolnGasVPSS::logStandardConc(int k) const { + double c = standardConcentration(k); + double lc = std::log(c); + return lc; + } + + /* + * + * getUnitsStandardConcentration() + * + * 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. + * + * 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 + * + * For EOS types other than cIdealSolidSolnPhase1, the default + * kmol/m3 holds for standard concentration units. For + * cIdealSolidSolnPhase0 type, the standard concentrtion is + * unitless. + */ + void IdealSolnGasVPSS::getUnitsStandardConc(double *uA, int, int sizeUA) const { + int eos = eosType(); + if (eos == cIdealSolnGasPhase0) { + for (int i = 0; i < sizeUA; i++) { + uA[i] = 0.0; + } + } else { + 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; + } + } + } + + + /* + * Get the array of non-dimensional activity coefficients + */ + void IdealSolnGasVPSS::getActivityCoefficients(doublereal *ac) const { + for (int k = 0; k < m_kk; k++) { + ac[k] = 1.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 IdealSolnGasVPSS::getChemPotentials_RT(doublereal* muRT) const{ + getChemPotentials(muRT); + doublereal invRT = 1.0 / _RT(); + for (int k = 0; k < m_kk; k++) { + muRT[k] *= invRT; + } + } + + void IdealSolnGasVPSS::getChemPotentials(doublereal* mu) const { + getStandardChemPotentials(mu); + doublereal xx; + doublereal rt = temperature() * GasConstant; + for (int k = 0; k < m_kk; k++) { + xx = fmaxx(SmallNumber, moleFraction(k)); + mu[k] += rt*(log(xx)); + } + } + + + void IdealSolnGasVPSS::getPartialMolarEnthalpies(doublereal* hbar) const { + getEnthalpy_RT(hbar); + doublereal rt = GasConstant * temperature(); + scale(hbar, hbar+m_kk, hbar, rt); + } + + void IdealSolnGasVPSS::getPartialMolarEntropies(doublereal* sbar) const { + getEntropy_R(sbar); + doublereal r = GasConstant; + scale(sbar, sbar+m_kk, sbar, r); + for (int k = 0; k < m_kk; k++) { + doublereal xx = fmaxx(SmallNumber, moleFraction(k)); + sbar[k] += r * ( - log(xx)); + } + } + + void IdealSolnGasVPSS::getPartialMolarIntEnergies(doublereal* ubar) const { + getIntEnergy_RT(ubar); + doublereal rt = GasConstant * temperature(); + scale(ubar, ubar+m_kk, ubar, rt); + } + + void IdealSolnGasVPSS::getPartialMolarCp(doublereal* cpbar) const { + getCp_R(cpbar); + doublereal r = GasConstant; + scale(cpbar, cpbar+m_kk, cpbar, r); + } + + void IdealSolnGasVPSS::getPartialMolarVolumes(doublereal* vbar) const { + getStandardVolumes(vbar); + } + + /* + * ----- Thermodynamic Values for the Species Reference States ---- + */ + + + + + /* + * Perform initializations after all species have been + * added. + */ + void IdealSolnGasVPSS::initThermo() { + initLengths(); + VPStandardStateTP::initThermo(); + } + + + void IdealSolnGasVPSS::setToEquilState(const doublereal* mu_RT) + { + double tmp, tmp2; + updateStandardStateThermo(); + const array_fp& grt = m_VPSS_ptr->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; + double m_p0 = m_VPSS_ptr->refPressure(); + 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]); + } + + /* + * Initialize the internal lengths. + * (this is not a virtual function) + */ + void IdealSolnGasVPSS::initLengths() { + m_kk = nSpecies(); + m_pp.resize(m_kk, 0.0); + } + + /* + * 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 IdealSolnGasVPSS::initThermoXML(XML_Node& phaseNode, std::string id) { + IdealSolnGasVPSS::initLengths(); + + if (phaseNode.hasChild("thermo")) { + XML_Node& thermoNode = phaseNode.child("thermo"); + std::string model = thermoNode["model"]; + if (model == "IdealGasVPSS") { + m_idealGas = 1; + } else if (model == "IdealSolnVPSS") { + m_idealGas = 0; + } else { + throw CanteraError("IdealSolnGasVPSS::initThermoXML", + "Unknown thermo model : " + model); + } + } + + /* + * Form of the standard concentrations. Must have one of: + * + * + * + * + */ + if (phaseNode.hasChild("standardConc")) { + if (m_idealGas) { + throw CanteraError("IdealSolnGasVPSS::initThermoXML", + "standardConc node for ideal gas"); + } + XML_Node& scNode = phaseNode.child("standardConc"); + string formStringa = scNode.attrib("model"); + string formString = lowercase(formStringa); + if (formString == "unity") { + m_formGC = 0; + } else if (formString == "molar_volume") { + m_formGC = 1; + } else if (formString == "solvent_volume") { + m_formGC = 2; + } else { + throw CanteraError("initThermoXML", + "Unknown standardConc model: " + formStringa); + } + } else { + if (!m_idealGas) { + throw CanteraError("initThermoXML", + "Unspecified standardConc model"); + } + } + + VPStandardStateTP::initThermoXML(phaseNode, id); + } + + void IdealSolnGasVPSS::setParametersFromXML(const XML_Node& thermoNode) { + VPStandardStateTP::setParametersFromXML(thermoNode); + std::string model = thermoNode["model"]; + if (model == "IdealGasVPSS") { + m_idealGas = 1; + } else if (model == "IdealSolnVPSS") { + m_idealGas = 0; + } else { + throw CanteraError("IdealSolnGasVPSS::initThermoXML", + "Unknown thermo model : " + model); + } + } + +} + + diff --git a/Cantera/src/thermo/IdealSolnGasVPSS.h b/Cantera/src/thermo/IdealSolnGasVPSS.h new file mode 100644 index 000000000..1f035946e --- /dev/null +++ b/Cantera/src/thermo/IdealSolnGasVPSS.h @@ -0,0 +1,452 @@ +/** + * @file IdealSolnGasVPSS.h + * Definition file for a derived class of ThermoPhase that assumes either + * an ideal gas or ideal solution approximation and handles + * variable pressure standard state methods for calculating + * thermodynamic properties (see \ref thermoprops and + * class \link Cantera::IdealSolnGasVPSS IdealSolnGasVPSS\endlink). + */ +/* + * 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$ + */ + +#ifndef CT_IDEALSOLNGASVPSS_H +#define CT_IDEALSOLNGASVPSS_H + +#include "VPStandardStateTP.h" +#include "VPSSMgr.h" + +namespace Cantera { + + class XML_Node; + class PDSS; + + /*! + * @name CONSTANTS - Models for the Standard State of IdealSolnPhase's + */ + //@{ + const int cIdealSolnGasPhaseG = 6009; + const int cIdealSolnGasPhase0 = 6010; + const int cIdealSolnGasPhase1 = 6011; + const int cIdealSolnGasPhase2 = 6012; + + + /** + * @ingroup thermoprops + * + * This class can handle either an ideal solution or an ideal gas approximation + * of a phase. + * + * + * @nosubgrouping + */ + class IdealSolnGasVPSS : public VPStandardStateTP { + + public: + + /*! + * + * @name Constructors and Duplicators for %IdealSolnGasVPSS + * + */ + /// Constructor. + IdealSolnGasVPSS(); + + IdealSolnGasVPSS(std::string infile, std::string id=""); + + /// Copy Constructor. + IdealSolnGasVPSS(const IdealSolnGasVPSS &); + + /// Assignment operator + IdealSolnGasVPSS& operator=(const IdealSolnGasVPSS &); + + /// Destructor. + virtual ~IdealSolnGasVPSS(); + + /* + * Duplication routine + */ + virtual ThermoPhase *duplMyselfAsThermoPhase() const; + + //@} + + /** + * @name Utilities (IdealSolnGasVPSS) + */ + //@{ + /** + * Equation of state type flag. The base class returns + * zero. Subclasses should define this to return a unique + * non-zero value. Constants defined for this purpose are + * listed in mix_defs.h. + */ + virtual int eosType() const; + + //@} + + /// Molar enthalpy. Units: J/kmol. + doublereal enthalpy_mole() const; + + /// Molar internal energy. Units: J/kmol. + doublereal intEnergy_mole() const; + + /// Molar entropy. Units: J/kmol/K. + doublereal entropy_mole() const; + + /// Molar Gibbs function. Units: J/kmol. + doublereal gibbs_mole() const; + + /// Molar heat capacity at constant pressure. Units: J/kmol/K. + doublereal cp_mole() const; + + /// Molar heat capacity at constant volume. Units: J/kmol/K. + doublereal cv_mole() const; + + /** + * @} + * @name Mechanical Properties + * @{ + */ + + //! Set the pressure in the fluid + /*! + * @param p pressure in pascals. + */ + void setPressure(doublereal p); + + //! 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; + + private: + /** + * Calculate the density of the mixture using the partial + * molar volumes and mole fractions as input + * + * The formula for this is + * + * \f[ + * \rho = \frac{\sum_k{X_k W_k}}{\sum_k{X_k V_k}} + * \f] + * + * where \f$X_k\f$ are the mole fractions, \f$W_k\f$ are + * the molecular weights, and \f$V_k\f$ are the pure species + * molar volumes. + * + * Note, the basis behind this formula is that in an ideal + * solution the partial molar volumes are equal to the + * species standard state molar volumes. + * The species molar volumes may be functions + * of temperature and pressure. + * + * NOTE: This is a non-virtual function, which is not a + * member of the ThermoPhase base class. + */ + void calcDensity(); + + public: + + //! 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; + + //! 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; + + //! 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. + * + * The base %ThermoPhase class assigns the default quantities + * of (kmol/m3) for all species. + * Inherited classes are responsible for overriding the default + * values if necessary. + * + * @param uA Output vector containing the units + * 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 + * @param k species index. Defaults to 0. + * @param sizeUA output int containing the size of the vector. + * Currently, this is equal to 6. + */ + virtual void getUnitsStandardConc(double *uA, int k = 0, + int sizeUA = 6) 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 (IdealSolnGasVPSS) + //@{ + + //! 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. No need for child + * classes to handle. + * + * @param mu Output vector of non-dimensional species chemical potentials + * Length: m_kk. + */ + void getChemPotentials_RT(doublereal* mu) 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 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 + * + * Properties of the standard states are delegated to the VPSSMgr object. + * The values are cached within this object, and are not recalculated unless + * the temperature or pressure changes. + */ + //@{ + + //@} + + /// @name Thermodynamic Values for the Species Reference States (IdealSolnGasVPSS) + /*! + * Properties of the reference states are delegated to the VPSSMgr object. + * The values are cached within this object, and are not recalculated unless + * the temperature or pressure changes. + */ + //@{ + + //@} + + + public: + + //! @name Initialization Methods - For Internal use (VPStandardState) + /*! + * The following methods are used in the process of constructing + * the phase and setting its parameters from a specification in an + * input file. They are not normally used in application programs. + * To see how they are used, see files importCTML.cpp and + * ThermoFactory.cpp. + */ + //@{ + + + //! 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. + * + * @param thermoNode An XML_Node object corresponding to + * the "thermo" entry for this phase in the input file. + */ + virtual void setParametersFromXML(const XML_Node& thermoNode); + + //! @internal Initialize the object + /*! + * 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 + */ + 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(). + */ + void setToEquilState(const doublereal* lambda_RT); + + //! Initialize a ThermoPhase object, potentially reading activity + //! coefficient information from an XML database. + /*! + * + * This routine initializes the lengths in the current object and + * then calls the parent routine. + * 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(). + * + * @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. + */ + virtual void initThermoXML(XML_Node& phaseNode, std::string id); + + private: + //! @internal Initialize the internal lengths in this object. + /*! + * Note this is not a virtual function and only handles + * this object + */ + void initLengths(); + + //@} + + protected: + + //! boolean indicating what ideal solution this is + /*! + * - 1 = ideal gas + * - 0 = ideal soln + */ + int m_idealGas; + + //! form of the generalized concentrations + /*! + * - 0 unity + * - 1 1/V_k + * - 2 1/V_0 + */ + int m_formGC; + + //! Temporary storage - length = m_kk. + vector_fp m_pp; + + }; +} + +#endif diff --git a/Cantera/src/thermo/Makefile.in b/Cantera/src/thermo/Makefile.in index 70e0d71ce..69b359afd 100644 --- a/Cantera/src/thermo/Makefile.in +++ b/Cantera/src/thermo/Makefile.in @@ -34,7 +34,10 @@ THERMO_OBJ = State.o Elements.o Constituents.o Phase.o \ ThermoPhase.o IdealGasPhase.o ConstDensityThermo.o \ SpeciesThermoFactory.o ConstCpPoly.o Nasa9Poly1.o Nasa9PolyMultiTempRegion.o \ Mu0Poly.o GeneralSpeciesThermo.o SurfPhase.o \ - ThermoFactory.o phasereport.o @phase_object_files@ + ThermoFactory.o phasereport.o \ + VPSSMgr.o VPSSMgrFactory.o VPSSMgr_General.o IdealSolnGasVPSS.o \ + VPSSMgr_IdealGas.o VPSSMgr_ConstVol.o PDSS_ConstVol.o PDSS_IdealGas.o \ + @phase_object_files@ THERMO_H = State.h Elements.h Constituents.h Phase.h mix_defs.h \ ThermoPhase.h IdealGasPhase.h ConstDensityThermo.h \ @@ -46,6 +49,8 @@ THERMO_H = State.h Elements.h Constituents.h Phase.h mix_defs.h \ GeneralSpeciesThermo.h Mu0Poly.h \ speciesThermoTypes.h SpeciesThermo.h SurfPhase.h \ EdgePhase.h \ + VPSSMgr.h VPSSMgrFactory.h VPSSMgr_General.h IdealSolnGasVPSS.h \ + VPSSMgr_IdealGas.h VPSSMgr_ConstVol.h PDSS_ConstVol.h PDSS_IdealGas.h \ @phase_header_files@ @@ -56,15 +61,18 @@ do_issp = 1 ELECTRO_OBJ = MolalityVPSSTP.o VPStandardStateTP.o \ IdealMolalSoln.o \ WaterPropsIAPWSphi.o WaterPropsIAPWS.o WaterProps.o \ - PDSS.o WaterPDSS.o \ + PDSS.o PDSS_Water.o PDSS_HKFT.o WaterPDSS.o \ HMWSoln.o HMWSoln_input.o DebyeHuckel.o \ - IdealGasPDSS.o WaterSSTP.o HKFT_PDSS.o + WaterSSTP.o \ + VPSSMgr_Water_ConstVol.o VPSSMgr_Water_HKFT.o -ELECTRO_H = MolalityVPSSTP.h VPStandardStateTP.h \ - IdealMolalSoln.h \ - WaterPropsIAPWSphi.h WaterPropsIAPWS.h WaterProps.h \ - PDSS.h WaterPDSS.h HMWSoln.h electrolytes.h \ - DebyeHuckel.h IdealGasPDSS.h WaterSSTP.h HKFT_PDSS.h +ELECTRO_H = MolalityVPSSTP.h VPStandardStateTP.h \ + IdealMolalSoln.h \ + WaterPropsIAPWSphi.h WaterPropsIAPWS.h WaterProps.h \ + PDSS.h PDSS_Water.h PDSS_HKFT.h \ + HMWSoln.h electrolytes.h WaterPDSS.h \ + DebyeHuckel.h WaterSSTP.h VPSSMgr_Water_HKFT.h \ + VPSSMgr_Water_ConstVol.h endif ifeq ($(do_issp),1) ISSP_OBJ = IdealSolidSolnPhase.o StoichSubstanceSSTP.o SingleSpeciesTP.o diff --git a/Cantera/src/thermo/MolalityVPSSTP.cpp b/Cantera/src/thermo/MolalityVPSSTP.cpp index a220e8ffe..ab6b06274 100644 --- a/Cantera/src/thermo/MolalityVPSSTP.cpp +++ b/Cantera/src/thermo/MolalityVPSSTP.cpp @@ -518,8 +518,7 @@ namespace Cantera { void MolalityVPSSTP::setState_TPM(doublereal t, doublereal p, const doublereal * const molalities) { setMolalities(molalities); - setTemperature(t); - setPressure(p); + setState_TP(t, p); } /* @@ -527,8 +526,7 @@ namespace Cantera { */ void MolalityVPSSTP::setState_TPM(doublereal t, doublereal p, compositionMap& m) { setMolalitiesByName(m); - setTemperature(t); - setPressure(p); + setState_TP(t, p); } /* @@ -536,8 +534,7 @@ namespace Cantera { */ void MolalityVPSSTP::setState_TPM(doublereal t, doublereal p, const std::string& m) { setMolalitiesByName(m); - setTemperature(t); - setPressure(p); + setState_TP(t, p); } diff --git a/Cantera/src/thermo/MolalityVPSSTP.h b/Cantera/src/thermo/MolalityVPSSTP.h index 58056f713..a6f1d1b3b 100644 --- a/Cantera/src/thermo/MolalityVPSSTP.h +++ b/Cantera/src/thermo/MolalityVPSSTP.h @@ -641,6 +641,7 @@ namespace Cantera { * element potentials. */ virtual void setToEquilState(const doublereal* lambda_RT) { + updateStandardStateThermo(); err("setToEquilState"); } diff --git a/Cantera/src/thermo/PDSS.cpp b/Cantera/src/thermo/PDSS.cpp index 257f3dcff..37cde085a 100644 --- a/Cantera/src/thermo/PDSS.cpp +++ b/Cantera/src/thermo/PDSS.cpp @@ -1,8 +1,8 @@ /** * @file PDSS.cpp - * * Implementation of a pressure dependent standard state - * virtual function. + * virtual function + * (see class \link Cantera::PDSS PDSS\endlink). */ /* * Copywrite (2006) Sandia Corporation. Under the terms of @@ -17,98 +17,91 @@ #include "xml.h" #include "ctml.h" #include "PDSS.h" -//#include "importCTML.h" + #include "ThermoFactory.h" #include "SpeciesThermo.h" -#include "ThermoPhase.h" +#include "VPStandardStateTP.h" namespace Cantera { /** * Basic list of constructors and duplicators */ PDSS::PDSS() : + m_pdssType(cPDSS_UNDEF), m_temp(-1.0), - m_dens(-1.0), + m_pres(-1.0), + m_p0(-1.0), m_tp(0), + m_vpssmgr_ptr(0), m_mw(0.0), m_spindex(-1), m_spthermo(0), - m_cp0_R_ptr(0), m_h0_RT_ptr(0), + m_cp0_R_ptr(0), m_s0_R_ptr(0), - m_g0_RT_ptr(0) + m_g0_RT_ptr(0), + m_V0_ptr(0), + m_hss_RT_ptr(0), + m_cpss_R_ptr(0), + m_sss_R_ptr(0), + m_gss_RT_ptr(0), + m_Vss_ptr(0) { } - PDSS::PDSS(ThermoPhase *tp, int spindex) : + PDSS::PDSS(VPStandardStateTP *tp, int spindex) : + m_pdssType(cPDSS_UNDEF), m_temp(-1.0), - m_dens(-1.0), + m_pres(-1.0), + m_p0(-1.0), m_tp(tp), + m_vpssmgr_ptr(0), m_mw(0.0), m_spindex(spindex), m_spthermo(0), - m_cp0_R_ptr(0), m_h0_RT_ptr(0), - m_s0_R_ptr(0), - m_g0_RT_ptr(0) - { - constructPDSS(tp, spindex); - if (tp) { - m_spthermo = &(tp->speciesThermo()); - } - } - - - PDSS::PDSS(ThermoPhase *tp, int spindex, std::string inputFile, std::string id) : - m_temp(-1.0), - m_dens(-1.0), - m_tp(tp), - m_mw(0.0), - m_spindex(spindex), - m_spthermo(0), m_cp0_R_ptr(0), - m_h0_RT_ptr(0), m_s0_R_ptr(0), - m_g0_RT_ptr(0) - { - constructPDSSFile(tp, spindex, inputFile, id); - if (tp) { - m_spthermo = &(tp->speciesThermo()); - } - } - - - PDSS::PDSS(ThermoPhase *tp, int spindex, XML_Node& phaseRoot, std::string id) : - m_temp(-1.0), - m_dens(-1.0), - m_tp(0), - m_mw(0.0), - m_spindex(0), - m_spthermo(0), - m_cp0_R_ptr(0), - m_h0_RT_ptr(0), - m_s0_R_ptr(0), - m_g0_RT_ptr(0) + m_g0_RT_ptr(0), + m_V0_ptr(0), + m_hss_RT_ptr(0), + m_cpss_R_ptr(0), + m_sss_R_ptr(0), + m_gss_RT_ptr(0), + m_Vss_ptr(0) { if (tp) { m_spthermo = &(tp->speciesThermo()); } - constructPDSSXML(tp, spindex, phaseRoot, id) ; + if (tp) { + m_vpssmgr_ptr = tp->provideVPSSMgr(); + } } + + PDSS::PDSS(const PDSS &b) : + m_pdssType(cPDSS_UNDEF), m_temp(-1.0), - m_dens(-1.0), + m_pres(-1.0), + m_p0(-1.0), m_tp(0), + m_vpssmgr_ptr(0), m_mw(b.m_mw), m_spindex(b.m_spindex), m_spthermo(b.m_spthermo), - m_cp0_R_ptr(b.m_cp0_R_ptr), m_h0_RT_ptr(b.m_h0_RT_ptr), + m_cp0_R_ptr(b.m_cp0_R_ptr), m_s0_R_ptr(b.m_s0_R_ptr), - m_g0_RT_ptr(b.m_g0_RT_ptr) + m_g0_RT_ptr(b.m_g0_RT_ptr), + m_V0_ptr(b.m_V0_ptr), + m_hss_RT_ptr(b.m_hss_RT_ptr), + m_cpss_R_ptr(b.m_cpss_R_ptr), + m_sss_R_ptr(b.m_sss_R_ptr), + m_gss_RT_ptr(b.m_gss_RT_ptr), + m_Vss_ptr(b.m_Vss_ptr) { /* * Use the assignment operator to do the brunt @@ -119,20 +112,31 @@ namespace Cantera { /** * Assignment operator + * ok -> we don't know what to do here, so we'll + * first implement a shallow copy. */ PDSS& PDSS::operator=(const PDSS&b) { if (&b == this) return *this; - m_tp = b.m_tp; - m_spindex = b.m_spindex; - m_spthermo = b.m_spthermo; - m_temp = b.m_temp; - m_dens = b.m_dens; - m_mw = b.m_mw; - m_spthermo = b.m_spthermo; - m_cp0_R_ptr = b.m_cp0_R_ptr; - m_h0_RT_ptr = b.m_h0_RT_ptr; - m_s0_R_ptr = b.m_s0_R_ptr; - m_g0_RT_ptr = b.m_g0_RT_ptr; + m_pdssType = b.m_pdssType; + m_temp = b.m_temp; + m_pres = b.m_pres; + m_p0 = b.m_p0; + m_tp = b.m_tp; + m_vpssmgr_ptr = b.m_vpssmgr_ptr; + m_mw = b.m_mw; + m_spindex = b.m_spindex; + m_spthermo = b.m_spthermo; + m_cp0_R_ptr = b.m_cp0_R_ptr; + m_h0_RT_ptr = b.m_h0_RT_ptr; + m_s0_R_ptr = b.m_s0_R_ptr; + m_g0_RT_ptr = b.m_g0_RT_ptr; + m_V0_ptr = b.m_V0_ptr; + m_cpss_R_ptr = b.m_cpss_R_ptr; + m_hss_RT_ptr = b.m_hss_RT_ptr; + m_sss_R_ptr = b.m_sss_R_ptr; + m_gss_RT_ptr = b.m_gss_RT_ptr; + m_Vss_ptr = b.m_Vss_ptr; + return *this; } @@ -151,91 +155,40 @@ namespace Cantera { PDSS *ip = new PDSS(*this); return ip; } - - - void PDSS::constructPDSS(ThermoPhase *tp, int spindex) { - initThermo(); - } - - /** - * constructPDSSXML: - * - * Initialization of a PDSS object using an - * xml file. - * - * This routine is a precursor to initThermo(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 PDSS::constructPDSSXML(ThermoPhase *tp, int spindex, - XML_Node& phaseNode, std::string id) { - initThermo(); - } - - /** - * constructPDSSFile(): - * - * Initialization of a PDSS object using an - * xml file. - * - * This routine is a precursor to initThermo(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 PDSS::constructPDSSFile(ThermoPhase *tp, int spindex, - std::string inputFile, std::string id) { - - if (inputFile.size() == 0) { - throw CanteraError("PDSS::initThermo", - "input file is null"); - } - std::string path = findInputFile(inputFile); - std::ifstream fin(path.c_str()); - if (!fin) { - throw CanteraError("PDSS::initThermo","could not open " - +path+" for reading."); - } - /* - * The phase object automatically constructs an XML object. - * Use this object to store information. - */ - - XML_Node *fxml = new XML_Node(); - fxml->build(fin); - XML_Node *fxml_phase = findXMLPhase(fxml, id); - if (!fxml_phase) { - throw CanteraError("PDSS::initThermo", - "ERROR: Can not find phase named " + - id + " in file named " + inputFile); - } - constructPDSSXML(tp, spindex, *fxml_phase, id); - delete fxml; - } - - void PDSS:: - initThermoXML(XML_Node& phaseNode, std::string id) { - initThermo(); + void PDSS::initThermoXML(const XML_Node& phaseNode, std::string& id) { + m_vpssmgr_ptr = m_tp->provideVPSSMgr(); } void PDSS::initThermo() { + m_vpssmgr_ptr = m_tp->provideVPSSMgr(); + initPtrs(); + } + + void PDSS::initAllPtrs(VPStandardStateTP *tp, VPSSMgr *vpssmgr_ptr, + SpeciesThermo* spthermo) { + m_tp = tp; + m_vpssmgr_ptr = vpssmgr_ptr; + m_spthermo = spthermo; + initPtrs(); + } + + void PDSS::initPtrs() { + m_h0_RT_ptr = &(m_vpssmgr_ptr->mPDSS_h0_RT[0]); + m_cp0_R_ptr = &(m_vpssmgr_ptr->mPDSS_cp0_R[0]); + m_s0_R_ptr = &(m_vpssmgr_ptr->mPDSS_s0_R[0]); + m_g0_RT_ptr = &(m_vpssmgr_ptr->mPDSS_g0_RT[0]); + m_V0_ptr = &(m_vpssmgr_ptr->mPDSS_V0[0]); + + m_hss_RT_ptr = &(m_vpssmgr_ptr->mPDSS_hss_RT[0]); + m_cpss_R_ptr = &(m_vpssmgr_ptr->mPDSS_cpss_R[0]); + m_sss_R_ptr = &(m_vpssmgr_ptr->mPDSS_sss_R[0]); + m_gss_RT_ptr = &(m_vpssmgr_ptr->mPDSS_gss_RT[0]); + m_Vss_ptr = &(m_vpssmgr_ptr->mPDSS_Vss[0]); } - void PDSS::setParametersFromXML(const XML_Node& eosdata) { - } + // Return the molar enthalpy in units of J kmol-1 /* @@ -244,10 +197,13 @@ namespace Cantera { * (NOTE: assumes that ThermoPhase Ref Polynomials are up-to-date) */ doublereal PDSS::enthalpy_mole() const { - //m_tp->_updateThermo(); - m_temp = m_tp->temperature(); - double RT = GasConstant * m_temp; - return m_h0_RT_ptr[m_spindex] * RT; + err("enthalpy_mole()"); + return (0.0); + } + + doublereal PDSS::enthalpy_RT() const { + err("enthalpy_RT()"); + return (0.0); } // Return the molar internal Energy in units of J kmol-1 @@ -258,7 +214,7 @@ namespace Cantera { * @return returns the species standard state internal Energy in J kmol-1 */ doublereal PDSS::intEnergy_mole() const { - throw CanteraError("PDSS::intEnergy_mole()", "unimplemented"); + err("intEnergy_mole()"); return (0.0); } @@ -270,7 +226,12 @@ namespace Cantera { * @return returns the species standard state entropy in J kmol-1 K-1 */ doublereal PDSS::entropy_mole() const { - throw CanteraError("PDSS::entropy_mole()", "unimplemented"); + err("entropy_mole()"); + return (0.0); + } + + doublereal PDSS::entropy_R() const { + err("entropy_R()"); return (0.0); } @@ -281,9 +242,13 @@ namespace Cantera { * * @return returns the species standard state gibbs free energy in J kmol-1 */ - doublereal PDSS:: - gibbs_mole() const { - throw CanteraError("PDSS::gibbs_mole()", "unimplemented"); + doublereal PDSS::gibbs_mole() const { + err("gibbs_mole()"); + return (0.0); + } + + doublereal PDSS::gibbs_RT() const { + err("gibbs_RT()"); return (0.0); } @@ -295,10 +260,20 @@ namespace Cantera { * @return returns the species standard state Cp in J kmol-1 K-1 */ doublereal PDSS::cp_mole() const { - throw CanteraError("PDSS::cp_mole()", "unimplemented"); + err("cp_mole()"); return (0.0); } + doublereal PDSS::cp_R() const { + err("cp_R()"); + return (0.0); + } + + doublereal PDSS::molarVolume() const { + err("molarVolume()"); + return 0.0; + } + // Return the molar const volume heat capacity in units of J kmol-1 K-1 /* * Returns the species standard state Cv in J kmol-1 K-1 at the @@ -307,10 +282,35 @@ namespace Cantera { * @return returns the species standard state Cv in J kmol-1 K-1 */ doublereal PDSS::cv_mole() const { - throw CanteraError("PDSS::cv_mole()", "unimplemented"); + err("cv_mole()"); return (0.0); } + doublereal PDSS::gibbs_RT_ref() const { + err("gibbs_RT_ref()"); + return 0.0; + } + + doublereal PDSS::enthalpy_RT_ref() const { + err("enthalpy_RT_ref()"); + return 0.0; + } + + doublereal PDSS::entropy_R_ref() const { + err("entropy_RT_ref()"); + return 0.0; + } + + doublereal PDSS::cp_R_ref() const { + err("entropy_RT_ref()"); + return 0.0; + } + + doublereal PDSS::molarVolume_ref() const { + err("molarVolume_ref()"); + return 0.0; + } + /** * Return the difference in enthalpy between current p * and ref p0, in mks units of @@ -318,31 +318,21 @@ namespace Cantera { */ doublereal PDSS:: enthalpyDelp_mole() const { - throw CanteraError("PDSS::enthalpy_mole()", "unimplemented"); - return (0.0); + doublereal RT = m_temp * GasConstant; + doublereal tmp = enthalpy_RT_ref(); + return(enthalpy_mole() - RT * tmp); } - /** - * Calculate difference in the internal energy between current p - * and ref p0, in mks units of - * J kmol-1 - */ - doublereal PDSS:: - intEnergyDelp_mole() const { - throw CanteraError("PDSS::enthalpyDelp_mole()", "unimplemented"); - return (0.0); - } /** * Return the difference in entropy between current p * and ref p0, in mks units of * J kmol-1 K-1 */ - doublereal PDSS:: - entropyDelp_mole() const { - - throw CanteraError("PDSS::entropyDelp_mole()", "unimplemented"); - return (0.0); + doublereal PDSS::entropyDelp_mole() const { + doublereal tmp = entropy_R_ref(); + return(entropy_mole() - GasConstant * tmp); + } /** @@ -350,10 +340,10 @@ namespace Cantera { * the ref p0, in mks units of * J kmol-1 K-1. */ - doublereal PDSS:: - gibbsDelp_mole() const { - throw CanteraError("PDSS::gibbsDelp_mole()", "unimplemented"); - return (0.0); + doublereal PDSS::gibbsDelp_mole() const { + doublereal RT = m_temp * GasConstant; + doublereal tmp = gibbs_RT_ref(); + return(gibbs_mole() - RT * tmp); } // Return the molar const volume heat capacity in units of J kmol-1 K-1 @@ -363,39 +353,21 @@ namespace Cantera { * * @return returns the species standard state Cv in J kmol-1 K-1 */ - doublereal PDSS:: - cpDelp_mole() const { - throw CanteraError("PDSS::cpDelp_mole()", "unimplemented"); - return (0.0); + doublereal PDSS::cpDelp_mole() const { + doublereal tmp = cp_R_ref(); + return(cp_mole() - GasConstant * tmp); } - /** - * Calculate the difference in constant volume heat capacity - * between the current p and the ref p0 - * in mks units of J kmol-1 K-1 - */ - doublereal PDSS:: - cvDelp_mole() const { - throw CanteraError("PDSS::cvDelp_mole()", "unimplemented"); - return (0.0); - } /** * Calculate the pressure (Pascals), given the temperature and density * Temperature: kelvin * rho: density in kg m-3 */ - doublereal PDSS:: - pressure() const { - throw CanteraError("PDSS::pressure()", "unimplemented"); - return (0.0); + doublereal PDSS::pressure() const { + return (m_pres); } - - void PDSS:: - setPressure(doublereal p) { - throw CanteraError("PDSS::pressure()", "unimplemented"); - } - + // Return the volumetric thermal expansion coefficient. Units: 1/K. /* * The thermal expansion coefficient is defined as @@ -410,36 +382,26 @@ namespace Cantera { /// critical temperature doublereal PDSS::critTemperature() const { - throw CanteraError("PDSS::critTemperature()", "unimplemented"); + err("critTemperature()"); return (0.0); } /// critical pressure doublereal PDSS::critPressure() const { - throw CanteraError("PDSS::critPressure()", "unimplemented"); + err("critPressure()"); return (0.0); } /// critical density doublereal PDSS::critDensity() const { - throw CanteraError("PDSS::critDensity()", "unimplemented"); + err("critDensity()"); return (0.0); } - - void PDSS::setDensity(double dens) { - m_dens = dens; + + void PDSS::setPressure(doublereal pres) { + m_pres = pres; } - /** - * Return the density of the standard state - * - * We assume that the storred density is current. - * Note, this is the density of the standard state, - * not of the mixture. - */ - double PDSS::density() const { - return m_dens; - } /** * Return the temperature @@ -447,33 +409,34 @@ namespace Cantera { * Obtain the temperature from the owning ThermoPhase object * if you can. */ - double PDSS::temperature() const { - if (m_tp) { - m_temp = m_tp->temperature(); - } + doublereal PDSS::temperature() const { return m_temp; } - void PDSS::setTemperature(double temp) { + void PDSS::setTemperature(doublereal temp) { m_temp = temp; } doublereal PDSS::molecularWeight() const { return m_mw; } - void PDSS::setMolecularWeight(double mw) { + void PDSS::setMolecularWeight(doublereal mw) { m_mw = mw; } - void PDSS::setState_TP(double temp, double pres) { - throw CanteraError("PDSS::setState_TP()", "unimplemented"); + void PDSS::setState_TP(doublereal temp, doublereal pres) { + err("setState_TP()"); } /// saturation pressure doublereal PDSS::satPressure(doublereal t){ - throw CanteraError("PDSS::satPressure()", "unimplemented"); + err("satPressure()"); return (0.0); } + void PDSS::err(std::string msg) const { + throw CanteraError("PDSS::" + msg, "unimplemented"); + } + } diff --git a/Cantera/src/thermo/PDSS.h b/Cantera/src/thermo/PDSS.h index 0ec40fdbb..a3c801e15 100644 --- a/Cantera/src/thermo/PDSS.h +++ b/Cantera/src/thermo/PDSS.h @@ -1,8 +1,8 @@ /** * @file PDSS.h - * - * Declares class PDSS pressure dependent standard state - * for a single species + * Declarations for the virtual base class PDSS (pressure dependent standard state) + * which handles calculations for a single species in a phase + * (see class \link Cantera::PDSS PDSS\endlink). */ /* * Copywrite (2006) Sandia Corporation. Under the terms of @@ -16,21 +16,22 @@ #ifndef CT_PDSS_H #define CT_PDSS_H #include "ct_defs.h" +#include "mix_defs.h" -class XML_Node; -class ThermoPhase; - - class WaterPropsIAPWS; +class WaterPropsIAPWS; namespace Cantera { - + + class XML_Node; class SpeciesThermo; + class VPStandardStateTP; + class VPSSMgr; //! Virtual base class for a species with a pressure dependent //! standard state /*! - * Virtual base class for calculation of the + * Virtual base class for calculation of the * pressure dependent standard state for a single species * * Class %PDSS is the base class @@ -50,14 +51,29 @@ namespace Cantera { * It only recalculates the standard state when the setState functions * for temperature and pressure are called. * + *

Thread Safety

+ * + * These classes are designed such that they are not thread safe when + * called by themselves. The reason for this is that they sometimes use + * shared SpeciesThermo resources where they set the states. This condition + * may be remedied in the future if we get serious about employing + * multithreaded capabilities by adding mutex locks to the + * SpeciesThermo resources. + * + * However, in many other respects they can be thread safe. They use + * separate memory and hold intermediate data. */ class PDSS { public: /** - * Empty Constructor + * @name Constructors + * @{ */ + + + //! Empty Constructor PDSS(); //! Constructor that initializes the object by examining the XML entries @@ -68,7 +84,7 @@ namespace Cantera { * @param tp Pointer to the ThermoPhase object pertaining to the phase * @param spindex Species index of the species in the phase */ - PDSS(ThermoPhase *tp, int spindex); + PDSS(VPStandardStateTP *tp, int spindex); //! Copy Constructor /*! @@ -82,33 +98,6 @@ namespace Cantera { */ PDSS& operator=(const PDSS&b); - //! Constructor that initializes the object by examining the input file - //! of the ThermoPhase object - /*! - * This function calls the constructPDSSFile member function. - * - * @param tp Pointer to the ThermoPhase object pertaining to the phase - * @param spindex Species index of the species in the phase - * @param inputFile String name of the input file - * @param id String name of the phase in the input file. The default - * is the empty string, in which case the first phase in the - * file is used. - */ - PDSS(ThermoPhase *tp, int spindex, std::string inputFile, std::string id = ""); - - //! Constructor that initializes the object by examining the input file - //! of the ThermoPhase object - /*! - * This function calls the constructPDSSXML member function. - * - * @param tp Pointer to the ThermoPhase object pertaining to the phase - * @param spindex Species index of the species in the phase - * @param phaseRef Reference to the XML tree containing the phase information. - * @param id String name of the phase in the input file. The default - * is the empty string, in which case the first phase in the - * file is used. - */ - PDSS(ThermoPhase *tp, int spindex, XML_Node& phaseRef, std::string id = ""); //! Destructor for the phase virtual ~PDSS(); @@ -124,7 +113,7 @@ namespace Cantera { virtual PDSS *duplMyselfAsPDSS() const; /** - * + * @} * @name Utilities * @{ */ @@ -133,11 +122,22 @@ namespace Cantera { /*! * @return Returns the integer # of the parameterization */ - virtual int pdssType() const { return -1; } + virtual PDSS_enumType reportPDSSType() const { return cPDSS_UNDEF; } + + private: + + //! Set an error within this object for an unhandled capability + /*! + * @param msg Message string for this error + */ + void err(std::string msg) const; + + public: /** * @} * @name Molar Thermodynamic Properties of the Species Standard State + * in the Solution * @{ */ @@ -150,6 +150,15 @@ namespace Cantera { */ virtual doublereal enthalpy_mole() const; + //! Return the standard state molar enthalpy divided by RT + /*! + * Returns the species standard state enthalpy divided by RT at the + * current temperature and pressure. + * + * @return returns the species standard state enthalpy in unitless form + */ + virtual doublereal enthalpy_RT() const; + //! Return the molar internal Energy in units of J kmol-1 /*! * Returns the species standard state internal Energy in J kmol-1 at the @@ -168,6 +177,15 @@ namespace Cantera { */ virtual doublereal entropy_mole() const; + //! Return the standard state entropy divided by RT + /*! + * Returns the species standard state entropy divided by RT at the + * current temperature and pressure. + * + * @return returns the species standard state entropy divided by RT + */ + virtual doublereal entropy_R() const; + //! Return the molar gibbs free energy in units of J kmol-1 /*! * Returns the species standard state gibbs free energy in J kmol-1 at the @@ -177,6 +195,15 @@ namespace Cantera { */ virtual doublereal gibbs_mole() const; + //! Return the molar gibbs free energy divided by RT + /*! + * Returns the species standard state gibbs free energy divided by RT at the + * current temperature and pressure. + * + * @return returns the species standard state gibbs free energy divided by RT + */ + virtual doublereal gibbs_RT() const; + //! Return the molar const pressure heat capacity in units of J kmol-1 K-1 /*! * Returns the species standard state Cp in J kmol-1 K-1 at the @@ -186,6 +213,15 @@ namespace Cantera { */ virtual doublereal cp_mole() const; + //! Return the molar const pressure heat capacity divided by RT + /*! + * Returns the species standard state Cp divided by RT at the + * current temperature and pressure. + * + * @return returns the species standard state Cp divided by RT + */ + virtual doublereal cp_R() const; + //! Return the molar const volume heat capacity in units of J kmol-1 K-1 /*! * Returns the species standard state Cv in J kmol-1 K-1 at the @@ -195,23 +231,108 @@ namespace Cantera { */ virtual doublereal cv_mole() const; - /* - * Get the difference in the standard state thermodynamic properties - * between the current pressure. and the reference pressure, p0 + //! Return the molar volume at standard state + /*! + * Returns the species standard state molar volume at the + * current temperature and pressure + * + * @return returns the standard state molar volume divided by R + * units are m**3 kmol-1. */ + virtual doublereal molarVolume() const; + + //! Get the difference in the standard state enthalpy + //! between the current pressure and the reference pressure, p0. virtual doublereal enthalpyDelp_mole() const; - virtual doublereal intEnergyDelp_mole() const; + + //! Get the difference in the standard state entropy between + //! the current pressure and the reference pressure, p0 virtual doublereal entropyDelp_mole() const; + + //! Get the difference in the standard state gibbs free energy + //! between the current pressure and the reference pressure, p0. virtual doublereal gibbsDelp_mole() const; + + //! Get the difference in standard state heat capacity + //! between the current pressure and the reference pressure, p0. virtual doublereal cpDelp_mole() const; - virtual doublereal cvDelp_mole() const; - //@} - /// @name Mechanical Equation of State Properties --------------------- - //@{ + /** + * @} + * @name Properties of the Reference State of the Species + * in the Solution + * @{ + */ + //! Return the reference pressure for this phase. + doublereal refPressure() const { + return m_p0; + } + + //! Return the molar gibbs free energy divided by RT at reference pressure + /*! + * Returns the species reference state gibbs free energy divided by RT at the + * current temperature. + * + * @return returns the reference state gibbs free energy divided by RT + */ + virtual doublereal gibbs_RT_ref() const; + + //! Return the molar enthalpy divided by RT at reference pressure + /*! + * Returns the species reference state enthalpy divided by RT at the + * current temperature. + * + * @return returns the reference state enthalpy divided by RT + */ + virtual doublereal enthalpy_RT_ref() const; + + //! Return the molar entropy divided by R at reference pressure + /*! + * Returns the species reference state entropy divided by R at the + * current temperature. + * + * @return returns the reference state entropy divided by R + */ + virtual doublereal entropy_R_ref() const; + + //! Return the molar heat capacity divided by R at reference pressure + /*! + * Returns the species reference state heat capacity divided by R at the + * current temperature. + * + * @return returns the reference state heat capacity divided by R + */ + virtual doublereal cp_R_ref() const; + + //! Return the molar volume at reference pressure + /*! + * Returns the species reference state molar volume at the + * current temperature. + * + * @return returns the reference state molar volume divided by R + * units are m**3 kmol-1. + */ + virtual doublereal molarVolume_ref() const; + + /** + * @} + * @name Mechanical Equation of State Properties + * @{ + */ + + //! Returns the pressure (Pa) virtual doublereal pressure() const; - virtual void setPressure(doublereal p); + + //! Sets the pressure in the object + /*! + * Currently, this sets the pressure in the PDSS object. + * It is indeterminant what happens to the owning VPStandardStateTP + * object and to the VPSSMgr object. + * + * @param pres Pressure to be set (Pascal) + */ + virtual void setPressure(doublereal pres); //! Return the volumetric thermal expansion coefficient. Units: 1/K. /*! @@ -226,74 +347,138 @@ namespace Cantera { /// @name Partial Molar Properties of the Solution ----------------- //@{ - virtual void getChemPotentials(doublereal* mu) const { - mu[0] = gibbs_mole(); - } + //! Set the internal temperature + /*! + * @param temp Temperature (Kelvin) + */ + virtual void setTemperature(doublereal temp); - //@} - /// @name Properties of the Standard State of the Species - // in the Solution -- - //@{ - + //! Return the current storred temperature + doublereal temperature() const; + + //! Set the internal temperature and pressure + /*! + * @param temp Temperature (Kelvin) + * @param pres pressure (Pascals) + */ + virtual void setState_TP(doublereal temp, doublereal pres); - /// critical temperature + /** + * @} + * @name Miscellaneous properties of the standard state + * @{ + */ + + //! critical temperature virtual doublereal critTemperature() const; - /// critical pressure + //! critical pressure virtual doublereal critPressure() const; - /// critical density + //! critical density virtual doublereal critDensity() const; - /// saturation temperature - //virtual doublereal satTemperature(doublereal p) const; - + //! saturation pressure + /*! + * @param T Temperature (Kelvin) + */ + virtual doublereal satPressure(doublereal T); - - /// saturation pressure - virtual doublereal satPressure(doublereal t); - - virtual void setDensity(double dens); - double density() const; - virtual void setTemperature(double temp); - double temperature() const; - virtual void setState_TP(double temp, double pres); - + //! Return the molecular weight of the species + //! in units of kg kmol-1 doublereal molecularWeight() const; - void setMolecularWeight(double mw); - - virtual void constructPDSS(ThermoPhase *tp, int spindex); - virtual void constructPDSSFile(ThermoPhase *tp, int spindex, - std::string inputFile, std::string id); - virtual void constructPDSSXML(ThermoPhase *tp, int spindex, - XML_Node& phaseNode, std::string id); - virtual void initThermoXML(XML_Node& eosdata, std::string id); + + //! Set the molecular weight of the species + /*! + * @param mw Molecular Weight in kg kmol-1 + */ + void setMolecularWeight(doublereal mw); + + /** + * @} + * @name Initialization of the Object + * @{ + */ + + + //! Initialization routine for all of the shallow pointers + /*! + * This is a cascading call, where each level should call the + * the parent level. + * + * The initThermo() routines get called before the initThermoXML() routines + * from the constructPDSSXML() routine. + * + * + * Calls initPtrs(); + */ virtual void initThermo(); - virtual void setParametersFromXML(const XML_Node& eosdata); + + //! Initialization routine for the PDSS object based on the phaseNode + /*! + * This is a cascading call, where each level should call the + * the parent level. + * + * @param phaseNode Reference to the phase Information for the phase + * that owns this species. + * + * @param id Optional parameter identifying the name of the + * phase. If none is given, the first XML + * phase element will be used. + */ + virtual void initThermoXML(const XML_Node& phaseNode, std::string& id); + + + //! Initialize all of the internal shallow pointers that can be initialized + /*! + * This routine isn't virtual + */ + void initPtrs(); + + //! Initialize or Reinitialize all shallow pointers in the object + /*! + * This command is called to reinitialize all shallow pointers in the + * object. It's needed for the duplicator capability + * + * @param vptp_ptr Pointer to the Variable pressure %ThermoPhase object + * This object must have already been malloced. + * + * @param vpssmgr_ptr Pointer to the variable pressure standard state + * calculator for this phase + * + * @param spthermo_ptr Pointer to the optional SpeciesThermo object + * that will handle the calculation of the reference + * state thermodynamic coefficients. + */ + void initAllPtrs(VPStandardStateTP *vptp_ptr, VPSSMgr *vpssmgr_ptr, + SpeciesThermo* spthermo_ptr); + + //@} protected: - /** - * state of the system (temperature and density); - * This may redundant and may go away. Should be able to - * get this information from owning ThermoPhase object. - */ + //! Enumerated type describing the type of the PDSS object + PDSS_enumType m_pdssType; + + //! Current temperature used by the PDSS object mutable doublereal m_temp; - /** - * state of the system (temperature and density); - * This may redundant and may go away. Should be able to - * get this information from owning ThermoPhase object. - */ - doublereal m_dens; + //! State of the system - pressure + mutable doublereal m_pres; - /** - * Thermophase which this species belongs to. Note, in some + //! reference state pressure of the species. + doublereal m_p0; + + //! Thermophase which this species belongs to. + /*! + * Note, in some * applications (i.e., mostly testing applications, this may be a null * value. Applications should test whether this is null before usage. */ - ThermoPhase *m_tp; + VPStandardStateTP *m_tp; + //! Pointer to the VPSS manager for this object + VPSSMgr *m_vpssmgr_ptr; /** * Molecular Weight of the species @@ -305,8 +490,8 @@ namespace Cantera { */ int m_spindex; - /** - * Pointer to the species thermodynamic property manager. + //! Pointer to the species thermodynamic property manager. + /*! * This is a copy of the pointer in the ThermoPhase object. * Note, this object doesn't own the pointer. * If the SpeciesThermo ThermoPhase object doesn't know @@ -314,12 +499,84 @@ namespace Cantera { * set to zero. */ SpeciesThermo* m_spthermo; - - doublereal *m_cp0_R_ptr; + + //! Reference state enthalpy divided by RT. + /*! + * Storage for the thermo properties is provided by + * VPSSMgr. + * Calculated at the current value of T and m_p0 + */ doublereal *m_h0_RT_ptr; + + //! Reference state heat capacity divided by R. + /*! + * Storage for the thermo properties is provided by + * VPSSMgr. + * Calculated at the current value of T and m_p0 + */ + doublereal *m_cp0_R_ptr; + + //! Reference state entropy divided by R. + /*! + * Storage for the thermo properties is provided by + * VPSSMgr. + * Calculated at the current value of T and m_p0 + */ doublereal *m_s0_R_ptr; + + //! Reference state gibbs free energy divided by RT. + /*! + * Calculated at the current value of T and m_p0 + */ doublereal *m_g0_RT_ptr; + //! Reference state molar volume (m3 kg-1) + /*! + * Storage for the thermo properties is provided by + * VPSSMgr. + * Calculated at the current value of T and m_p0 + */ + doublereal *m_V0_ptr; + + //! Standard state enthalpy divided by RT. + /*! + * Storage for the thermo properties is provided by + * VPSSMgr. + * Calculated at the current value of T and P + */ + doublereal *m_hss_RT_ptr; + + //! Standard state heat capacity divided by R. + /*! + * Storage for the thermo properties is provided by + * VPSSMgr. + * Calculated at the current value of T and P + */ + doublereal *m_cpss_R_ptr; + + //! Standard state entropy divided by R. + /*! + * Storage for the thermo properties is provided by + * VPSSMgr. + * Calculated at the current value of T and P + */ + doublereal *m_sss_R_ptr; + + //! Standard state gibbs free energy divided by RT. + /*! + * Storage for the thermo properties is provided by + * VPSSMgr. + * Calculated at the current value of T and P + */ + doublereal *m_gss_RT_ptr; + + //! Standard State molar volume (m3 kg-1) + /*! + * Storage for the thermo properties is provided by + * VPSSMgr. + * Calculated at the current value of T and P + */ + doublereal *m_Vss_ptr; }; diff --git a/Cantera/src/thermo/PDSSFactory.cpp b/Cantera/src/thermo/PDSSFactory.cpp new file mode 100644 index 000000000..e3439b997 --- /dev/null +++ b/Cantera/src/thermo/PDSSFactory.cpp @@ -0,0 +1,46 @@ +/** + * @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 "Nasa9PolyMultiTempRegion.h" +#include "Nasa9Poly1.h" + +#ifdef WITH_ADSORBATE +#include "AdsorbateThermo.h" +#endif + +#include "SpeciesThermoMgr.h" +#include "speciesThermoTypes.h" +#include "VPSSMgr.h" + +#include "xml.h" +#include "ctml.h" + +using namespace ctml; + + +namespace Cantera { + + +} diff --git a/Cantera/src/thermo/PDSS_ConstVol.cpp b/Cantera/src/thermo/PDSS_ConstVol.cpp new file mode 100644 index 000000000..b8afd7263 --- /dev/null +++ b/Cantera/src/thermo/PDSS_ConstVol.cpp @@ -0,0 +1,350 @@ +/** + * @file PDSS_ConstVol.cpp + * Implementation of a pressure dependent standard state + * virtual function. + */ +/* + * Copywrite (2006) Sandia Corporation. Under the terms of + * Contract DE-AC04-94AL85000 with Sandia Corporation, the + * U.S. Government retains certain rights in this software. + */ +/* + * $Id$ + */ + +#include "ct_defs.h" +#include "xml.h" +#include "ctml.h" +#include "PDSS_ConstVol.h" +#include "ThermoFactory.h" + +#include "VPStandardStateTP.h" + +using namespace std; + +namespace Cantera { + /** + * Basic list of constructors and duplicators + */ + + PDSS_ConstVol::PDSS_ConstVol(VPStandardStateTP *tp, int spindex) : + PDSS(tp, spindex) + { + m_pdssType = cPDSS_CONSTVOL; + } + + + PDSS_ConstVol::PDSS_ConstVol(VPStandardStateTP *tp, int spindex, std::string inputFile, std::string id) : + PDSS(tp, spindex) + { + m_pdssType = cPDSS_CONSTVOL; + constructPDSSFile(tp, spindex, inputFile, id); + } + + PDSS_ConstVol::PDSS_ConstVol(VPStandardStateTP *tp, int spindex, + const XML_Node& speciesNode, + const XML_Node& phaseRoot, + bool spInstalled) : + PDSS(tp, spindex) + { + m_pdssType = cPDSS_CONSTVOL; + + constructPDSSXML(tp, spindex, speciesNode, phaseRoot, spInstalled) ; + } + + + PDSS_ConstVol::PDSS_ConstVol(const PDSS_ConstVol &b) : + PDSS(b) + { + /* + * Use the assignment operator to do the brunt + * of the work for the copy construtor. + */ + *this = b; + } + + /** + * Assignment operator + */ + PDSS_ConstVol& PDSS_ConstVol::operator=(const PDSS_ConstVol&b) { + if (&b == this) return *this; + PDSS::operator=(b); + return *this; + } + + PDSS_ConstVol::~PDSS_ConstVol() { + } + + //! Duplicator + PDSS* PDSS_ConstVol::duplMyselfAsPDSS() const { + PDSS_ConstVol * idg = new PDSS_ConstVol(*this); + return (PDSS *) idg; + } + + /** + * constructPDSSXML: + * + * Initialization of a PDSS_ConstVol object using an + * xml file. + * + * This routine is a precursor to initThermo(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 PDSS_ConstVol::constructPDSSXML(VPStandardStateTP *tp, int spindex, + const XML_Node& speciesNode, + const XML_Node& phaseNode, bool spInstalled) { + PDSS::initThermo(); + SpeciesThermo &sp = m_tp->speciesThermo(); + m_p0 = sp.refPressure(m_spindex); + + if (!spInstalled) { + throw CanteraError("PDSS_ConstVol::constructPDSSXML", "spInstalled false not handled"); + } + + const XML_Node *ss = speciesNode.findByName("standardState"); + if (!ss) { + throw CanteraError("PDSS_ConstVol::constructPDSSXML", + "no standardState Node for species " + speciesNode.name()); + } + std::string model = (*ss)["model"]; + if (model != "constant_incompressible") { + throw CanteraError("PDSS_ConstVol::initThermoXML", + "standardState model for species isn't constant_incompressible: " + speciesNode.name()); + } + + m_constMolarVolume = getFloat(*ss, "molarVolume", "-"); + + std::string id = ""; + initThermoXML(phaseNode, id); + } + + + /** + * constructPDSSFile(): + * + * Initialization of a PDSS_ConstVol object using an + * xml file. + * + * This routine is a precursor to initThermo(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 PDSS_ConstVol::constructPDSSFile(VPStandardStateTP *tp, int spindex, + std::string inputFile, std::string id) { + + if (inputFile.size() == 0) { + throw CanteraError("PDSS_ConstVol::initThermo", + "input file is null"); + } + std::string path = findInputFile(inputFile); + ifstream fin(path.c_str()); + if (!fin) { + throw CanteraError("PDSS_ConstVol::initThermo","could not open " + +path+" for reading."); + } + /* + * The phase object automatically constructs an XML object. + * Use this object to store information. + */ + + XML_Node *fxml = new XML_Node(); + fxml->build(fin); + XML_Node *fxml_phase = findXMLPhase(fxml, id); + if (!fxml_phase) { + throw CanteraError("PDSS_ConstVol::initThermo", + "ERROR: Can not find phase named " + + id + " in file named " + inputFile); + } + + XML_Node& speciesList = fxml_phase->child("speciesArray"); + XML_Node* speciesDB = get_XML_NameID("speciesData", speciesList["datasrc"], + &(fxml_phase->root())); + const vector&sss = tp->speciesNames(); + const XML_Node* s = speciesDB->findByAttr("name", sss[spindex]); + + constructPDSSXML(tp, spindex, *s, *fxml_phase, true); + delete fxml; + } + + void PDSS_ConstVol::initThermoXML(const XML_Node& phaseNode, std::string id) { + PDSS::initThermoXML(phaseNode, id); + } + + void PDSS_ConstVol::initThermo() { + PDSS::initThermo(); + SpeciesThermo &sp = m_tp->speciesThermo(); + m_p0 = sp.refPressure(m_spindex); + m_V0_ptr[m_spindex] = m_constMolarVolume; + m_Vss_ptr[m_spindex] = m_constMolarVolume; + } + + doublereal + PDSS_ConstVol::enthalpy_mole() const { + double val = enthalpy_RT(); + double RT = GasConstant * m_temp; + return (val * RT); + } + + doublereal + PDSS_ConstVol::enthalpy_RT() const { + double val = m_hss_RT_ptr[m_spindex]; + return (val); + } + + + doublereal + PDSS_ConstVol::intEnergy_mole() const { + doublereal pVRT = (m_pres * m_Vss_ptr[m_spindex]) / (GasConstant * m_temp); + double val = m_h0_RT_ptr[m_spindex] - pVRT; + double RT = GasConstant * m_temp; + return (val * RT); + } + + + doublereal + PDSS_ConstVol::entropy_mole() const { + double val = entropy_R(); + return (val * GasConstant); + } + + doublereal + PDSS_ConstVol::entropy_R() const { + double val = m_sss_R_ptr[m_spindex]; + return (val); + } + + /** + * Calculate the Gibbs free energy in mks units of + * J kmol-1 K-1. + */ + doublereal + PDSS_ConstVol::gibbs_mole() const { + double val = gibbs_RT(); + double RT = GasConstant * m_temp; + return (val * RT); + } + + doublereal + PDSS_ConstVol::gibbs_RT() const { + double val = m_gss_RT_ptr[m_spindex]; + return (val); + } + + doublereal + PDSS_ConstVol::cp_mole() const { + double val = m_cpss_R_ptr[m_spindex]; + return (val * GasConstant); + } + + doublereal + PDSS_ConstVol::cp_R() const { + double val = m_cpss_R_ptr[m_spindex]; + return (val); + } + + doublereal + PDSS_ConstVol::cv_mole() const { + double val = (cp_mole() - m_V0_ptr[m_spindex]); + return (val); + } + + doublereal + PDSS_ConstVol::molarVolume() const { + double val = m_Vss_ptr[m_spindex]; + return (val); + } + + doublereal + PDSS_ConstVol::gibbs_RT_ref() const { + double val = m_g0_RT_ptr[m_spindex]; + return (val); + } + + doublereal PDSS_ConstVol::enthalpy_RT_ref() const { + double val = m_h0_RT_ptr[m_spindex]; + return (val); + } + + doublereal PDSS_ConstVol::entropy_R_ref() const { + double val = m_s0_R_ptr[m_spindex]; + return (val); + } + + doublereal PDSS_ConstVol::cp_R_ref() const { + double val = m_cp0_R_ptr[m_spindex]; + return (val); + } + + doublereal PDSS_ConstVol::molarVolume_ref() const { + double val = m_V0_ptr[m_spindex]; + return (val); + } + + + + /// critical temperature + doublereal PDSS_ConstVol::critTemperature() const { + throw CanteraError("PDSS_ConstVol::critTemperature()", "unimplemented"); + return (0.0); + } + + /// critical pressure + doublereal PDSS_ConstVol::critPressure() const { + throw CanteraError("PDSS_ConstVol::critPressure()", "unimplemented"); + return (0.0); + } + + /// critical density + doublereal PDSS_ConstVol::critDensity() const { + throw CanteraError("PDSS_ConstVol::critDensity()", "unimplemented"); + return (0.0); + } + + void PDSS_ConstVol::setPressure(doublereal p) { + m_pres = p; + doublereal del_pRT = (m_pres - m_p0) / (GasConstant * m_temp); + m_hss_RT_ptr[m_spindex] = m_h0_RT_ptr[m_spindex] + del_pRT * m_Vss_ptr[m_spindex]; + m_gss_RT_ptr[m_spindex] = m_hss_RT_ptr[m_spindex] - m_sss_R_ptr[m_spindex]; + } + + void PDSS_ConstVol::setTemperature(double temp) { + m_temp = temp; + m_spthermo->update_one(m_spindex, temp, + m_cp0_R_ptr, m_h0_RT_ptr, m_s0_R_ptr); + m_g0_RT_ptr[m_spindex] = m_h0_RT_ptr[m_spindex] - m_s0_R_ptr[m_spindex]; + + doublereal del_pRT = (m_pres - m_p0) / (GasConstant * m_temp); + + m_hss_RT_ptr[m_spindex] = m_h0_RT_ptr[m_spindex] + del_pRT * m_Vss_ptr[m_spindex]; + m_cpss_R_ptr[m_spindex] = m_cp0_R_ptr[m_spindex]; + m_sss_R_ptr[m_spindex] = m_s0_R_ptr[m_spindex]; + m_gss_RT_ptr[m_spindex] = m_hss_RT_ptr[m_spindex] - m_sss_R_ptr[m_spindex]; + + } + + + void PDSS_ConstVol::setState_TP(double temp, double pres) { + setTemperature(temp); + setPressure(pres); + } + + /// saturation pressure + doublereal PDSS_ConstVol::satPressure(doublereal t){ + throw CanteraError("PDSS_ConstVol::satPressure()", "unimplemented"); + return (0.0); + } + +} diff --git a/Cantera/src/thermo/PDSS_ConstVol.h b/Cantera/src/thermo/PDSS_ConstVol.h new file mode 100644 index 000000000..26a5389bc --- /dev/null +++ b/Cantera/src/thermo/PDSS_ConstVol.h @@ -0,0 +1,408 @@ +/** + * @file PDSS_ConstVol.h + * Declarations for the class PDSS_ConstVol (pressure dependent standard state) + * which handles calculations for a single species with a constant molar volume in a phase + * (see class \link Cantera::PDSS_ConstVol PDSS_ConstVol\endlink). + */ +/* + * Copywrite (2006) Sandia Corporation. Under the terms of + * Contract DE-AC04-94AL85000 with Sandia Corporation, the + * U.S. Government retains certain rights in this software. + */ +/* + * $Id$ + */ + +#ifndef CT_PDSS_CONSTVOL_H +#define CT_PDSS_CONSTVOL_H + +#include "PDSS.h" + +namespace Cantera { + class XML_Node; + class VPStandardStateTP; + + /** + * Class for pressure dependent standard states. + * This class is for a single Ideal Gas species. + * + */ + class PDSS_ConstVol : public PDSS { + + public: + + /** + * @name Constructors + * @{ + */ + + //! Constructor + /*! + * @param tp Pointer to the ThermoPhase object pertaining to the phase + * @param spindex Species index of the species in the phase + */ + PDSS_ConstVol(VPStandardStateTP *tp, int spindex); + + + //! Constructor that initializes the object by examining the input file + //! of the ThermoPhase object + /*! + * This function calls the constructPDSSFile member function. + * + * @param tp Pointer to the ThermoPhase object pertaining to the phase + * @param spindex Species index of the species in the phase + * @param inputFile String name of the input file + * @param id String name of the phase in the input file. The default + * is the empty string, in which case the first phase in the + * file is used. + */ + PDSS_ConstVol(VPStandardStateTP *tp, int spindex, + std::string inputFile, std::string id = ""); + + //! Constructor that initializes the object by examining the input file + //! of the ThermoPhase object + /*! + * This function calls the constructPDSSXML member function. + * + * @param vptp_ptr Pointer to the ThermoPhase object pertaining to the phase + * @param spindex Species index of the species in the phase + * @param speciesNode Reference to the species XML tree. + * @param phaseRef Reference to the XML tree containing the phase information. + * @param spInstalled Boolean indicating whether the species is installed yet + * or not. + */ + PDSS_ConstVol(VPStandardStateTP *vptp_ptr, int spindex, const XML_Node& speciesNode, + const XML_Node& phaseRef, bool spInstalled); + + //! Copy Constructur + /*! + * @param b Object to be copied + */ + PDSS_ConstVol(const PDSS_ConstVol &b); + + //! Assignment operator + /*! + * @param b Object to be copeid + */ + PDSS_ConstVol& operator=(const PDSS_ConstVol&b); + + //! Destructor + virtual ~PDSS_ConstVol(); + + //! Duplicator + virtual PDSS *duplMyselfAsPDSS() const; + + /** + * @} + * @name Utilities + * @{ + */ + virtual int pdssType() const { return -1; } + + /** + * @} + * @name Molar Thermodynamic Properties of the Species Standard State + * in the Solution + * @{ + */ + + //! Return the molar enthalpy in units of J kmol-1 + /*! + * Returns the species standard state enthalpy in J kmol-1 at the + * current temperature and pressure. + * + * @return returns the species standard state enthalpy in J kmol-1 + */ + virtual doublereal enthalpy_mole() const; + + //! Return the standard state molar enthalpy divided by RT + /*! + * Returns the species standard state enthalpy divided by RT at the + * current temperature and pressure. + * + * @return returns the species standard state enthalpy in unitless form + */ + virtual doublereal enthalpy_RT() const; + + //! Return the molar internal Energy in units of J kmol-1 + /*! + * Returns the species standard state internal Energy in J kmol-1 at the + * current temperature and pressure. + * + * @return returns the species standard state internal Energy in J kmol-1 + */ + virtual doublereal intEnergy_mole() const; + + //! Return the molar entropy in units of J kmol-1 K-1 + /*! + * Returns the species standard state entropy in J kmol-1 K-1 at the + * current temperature and pressure. + * + * @return returns the species standard state entropy in J kmol-1 K-1 + */ + virtual doublereal entropy_mole() const; + + //! Return the standard state entropy divided by RT + /*! + * Returns the species standard state entropy divided by RT at the + * current temperature and pressure. + * + * @return returns the species standard state entropy divided by RT + */ + virtual doublereal entropy_R() const; + + //! Return the molar gibbs free energy in units of J kmol-1 + /*! + * Returns the species standard state gibbs free energy in J kmol-1 at the + * current temperature and pressure. + * + * @return returns the species standard state gibbs free energy in J kmol-1 + */ + virtual doublereal gibbs_mole() const; + + //! Return the molar gibbs free energy divided by RT + /*! + * Returns the species standard state gibbs free energy divided by RT at the + * current temperature and pressure. + * + * @return returns the species standard state gibbs free energy divided by RT + */ + virtual doublereal gibbs_RT() const; + + //! Return the molar const pressure heat capacity in units of J kmol-1 K-1 + /*! + * Returns the species standard state Cp in J kmol-1 K-1 at the + * current temperature and pressure. + * + * @return returns the species standard state Cp in J kmol-1 K-1 + */ + virtual doublereal cp_mole() const; + + //! Return the molar const pressure heat capacity divided by RT + /*! + * Returns the species standard state Cp divided by RT at the + * current temperature and pressure. + * + * @return returns the species standard state Cp divided by RT + */ + virtual doublereal cp_R() const; + + //! Return the molar const volume heat capacity in units of J kmol-1 K-1 + /*! + * Returns the species standard state Cv in J kmol-1 K-1 at the + * current temperature and pressure. + * + * @return returns the species standard state Cv in J kmol-1 K-1 + */ + virtual doublereal cv_mole() const; + + //! Return the molar volume at standard state + /*! + * Returns the species standard state molar volume at the + * current temperature and pressure + * + * @return returns the standard state molar volume divided by R + * units are m**3 kmol-1. + */ + virtual doublereal molarVolume() const; + + /** + * @} + * @name Properties of the Reference State of the Species + * in the Solution + * @{ + */ + + //! Return the molar gibbs free energy divided by RT at reference pressure + /*! + * Returns the species reference state gibbs free energy divided by RT at the + * current temperature. + * + * @return returns the reference state gibbs free energy divided by RT + */ + virtual doublereal gibbs_RT_ref() const; + + //! Return the molar enthalpy divided by RT at reference pressure + /*! + * Returns the species reference state enthalpy divided by RT at the + * current temperature. + * + * @return returns the reference state enthalpy divided by RT + */ + virtual doublereal enthalpy_RT_ref() const; + + //! Return the molar entropy divided by R at reference pressure + /*! + * Returns the species reference state entropy divided by R at the + * current temperature. + * + * @return returns the reference state entropy divided by R + */ + virtual doublereal entropy_R_ref() const; + + //! Return the molar heat capacity divided by R at reference pressure + /*! + * Returns the species reference state heat capacity divided by R at the + * current temperature. + * + * @return returns the reference state heat capacity divided by R + */ + virtual doublereal cp_R_ref() const; + + //! Return the molar volume at reference pressure + /*! + * Returns the species reference state molar volume at the + * current temperature. + * + * @return returns the reference state molar volume divided by R + * units are m**3 kmol-1. + */ + virtual doublereal molarVolume_ref() const; + + /** + * @} + * @name Mechanical Equation of State Properties + * @{ + */ + + //! Sets the pressure in the object + /*! + * Currently, this sets the pressure in the PDSS object. + * It is indeterminant what happens to the owning VPStandardStateTP + * object and to the VPSSMgr object. + * + * @param pres Pressure to be set (Pascal) + */ + virtual void setPressure(doublereal pres); + + //! Set the internal temperature + /*! + * @param temp Temperature (Kelvin) + */ + virtual void setTemperature(double temp); + + //! Set the internal temperature and pressure + /*! + * @param temp Temperature (Kelvin) + * @param pres pressure (Pascals) + */ + virtual void setState_TP(double temp, double pres); + + /** + * @} + * @name Miscellaneous properties of the standard state + * @{ + */ + + /// critical temperature + virtual doublereal critTemperature() const; + + /// critical pressure + virtual doublereal critPressure() const; + + /// critical density + virtual doublereal critDensity() const; + + /// saturation pressure + /*! + * @param t Temperature (kelvin) + */ + virtual doublereal satPressure(doublereal t); + + /** + * @} + * @name Initialization of the Object + * @{ + */ + + //! Initialization routine for all of the shallow pointers + /*! + * This is a cascading call, where each level should call the + * the parent level. + * + * The initThermo() routines get called before the initThermoXML() routines + * from the constructPDSSXML() routine. + * + * + * Calls initPtrs(); + */ + virtual void initThermo(); + + //! Initialization of a PDSS object using an + //! input XML file. + /*! + * + * This routine is a precursor to constructPDSSXML(XML_Node*) + * routine, which does most of the work. + * + * @param vptp_ptr Pointer to the Variable pressure %ThermoPhase object + * This object must have already been malloced. + * + * @param spindex Species index within the phase + * + * @param inputFile 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 constructPDSSFile(VPStandardStateTP *vptp_ptr, int spindex, + std::string inputFile, std::string id); + + //! Initialization of a PDSS object using an xml tree + /*! + * This routine is a driver for the initialization of the + * object. + * + * basic logic: + * initThermo() (cascade) + * getStuff from species Part of XML file + * initThermoXML(phaseNode) (cascade) + * + * @param vptp_ptr Pointer to the Variable pressure %ThermoPhase object + * This object must have already been malloced. + * + * @param spindex Species index within the phase + * + * @param speciesNode XML Node containing the species information + * + * @param phaseNode Reference to the phase Information for the phase + * that owns this species. + * + * @param spInstalled Boolean indicating whether the species is + * already installed. + */ + void constructPDSSXML(VPStandardStateTP *vptp_ptr, int spindex, + const XML_Node& speciesNode, + const XML_Node& phaseNode, bool spInstalled); + + //! Initialization routine for the PDSS object based on the phaseNode + /*! + * This is a cascading call, where each level should call the + * the parent level. + * + * @param phaseNode Reference to the phase Information for the phase + * that owns this species. + * + * @param id Optional parameter identifying the name of the + * phase. If none is given, the first XML + * phase element will be used. + */ + virtual void initThermoXML(const XML_Node& phaseNode, std::string id); + + //@} + + private: + + //! Value of the constant molar volume for the species + doublereal m_constMolarVolume; + + }; + +} + +#endif + + + diff --git a/Cantera/src/thermo/PDSS_HKFT.cpp b/Cantera/src/thermo/PDSS_HKFT.cpp new file mode 100644 index 000000000..2cecefc21 --- /dev/null +++ b/Cantera/src/thermo/PDSS_HKFT.cpp @@ -0,0 +1,301 @@ +/* + * $Id$ + */ +#include "ct_defs.h" +#include "xml.h" +#include "ctml.h" +#include "PDSS_HKFT.h" + +#include "VPStandardStateTP.h" + +using namespace std; + +namespace Cantera { + /** + * Basic list of constructors and duplicators + */ + + + + PDSS_HKFT::PDSS_HKFT(VPStandardStateTP *tp, int spindex) : + PDSS(tp, spindex) + { + } + + + PDSS_HKFT::PDSS_HKFT(VPStandardStateTP *tp, int spindex, std::string inputFile, std::string id) : + PDSS(tp, spindex) + { + } + + PDSS_HKFT::PDSS_HKFT(VPStandardStateTP *tp, int spindex, const XML_Node& speciesNode, + const XML_Node& phaseRoot, bool spInstalled) : + PDSS(tp, spindex) + { + } + + PDSS_HKFT::PDSS_HKFT(const PDSS_HKFT &b) : + PDSS(b) + { + /* + * Use the assignment operator to do the brunt + * of the work for the copy construtor. + */ + *this = b; + } + + /** + * Assignment operator + */ + PDSS_HKFT& PDSS_HKFT::operator=(const PDSS_HKFT&b) { + if (&b == this) return *this; + m_tp = b.m_tp; + m_spindex = b.m_spindex; + m_temp = b.m_temp; + m_pres = b.m_pres; + m_mw = b.m_mw; + return *this; + } + + /** + * Destructor for the PDSS_HKFT class + */ + PDSS_HKFT::~PDSS_HKFT() { + } + + + + + + /** + * Return the molar enthalpy in units of J kmol-1 + */ + doublereal + PDSS_HKFT::enthalpy_mole() const { + throw CanteraError("PDSS_HKFT::enthalpy_mole()", "unimplemented"); + return (0.0); + } + + doublereal + PDSS_HKFT::enthalpy_RT() const { + throw CanteraError("PDSS_HKFT::enthalpy_RT()", "unimplemented"); + return (0.0); + } + + /** + * Calculate the internal energy in mks units of + * J kmol-1 + */ + doublereal + PDSS_HKFT::intEnergy_mole() const { + throw CanteraError("PDSS_HKFT::enthalpy_mole()", "unimplemented"); + return (0.0); + } + + /** + * Calculate the entropy in mks units of + * J kmol-1 K-1 + */ + doublereal + PDSS_HKFT::entropy_mole() const { + + throw CanteraError("PDSS_HKFT::entropy_mole()", "unimplemented"); + return (0.0); + } + + /** + * Calculate the Gibbs free energy in mks units of + * J kmol-1 K-1. + */ + doublereal + PDSS_HKFT::gibbs_mole() const { + throw CanteraError("PDSS_HKFT::gibbs_mole()", "unimplemented"); + return (0.0); + } + + /** + * Calculate the constant pressure heat capacity + * in mks units of J kmol-1 K-1 + */ + doublereal + PDSS_HKFT::cp_mole() const { + throw CanteraError("PDSS_HKFT::cp_mole()", "unimplemented"); + return (0.0); + } + + /** + * Calculate the constant volume heat capacity + * in mks units of J kmol-1 K-1 + */ + doublereal + PDSS_HKFT::cv_mole() const { + throw CanteraError("PDSS_HKFT::cv_mole()", "unimplemented"); + return (0.0); + } + + doublereal + PDSS_HKFT::molarVolume() const { + throw CanteraError("PDSS_HKFT::molarVolume()", "unimplemented"); + return (0.0); + } + + doublereal + PDSS_HKFT::gibbs_RT_ref() const { + throw CanteraError("PDSS_HKFT::gibbs_RT_ref()", "unimplemented"); + return (0.0); + } + + doublereal + PDSS_HKFT::enthalpy_RT_ref() const { + throw CanteraError("PDSS_HKFT::enthalpy_RT_ref()", "unimplemented"); + return (0.0); + } + + doublereal + PDSS_HKFT::entropy_R_ref() const { + throw CanteraError("PDSS_HKFT::entropy_RT_ref()", "unimplemented"); + return (0.0); + } + + doublereal + PDSS_HKFT::cp_R_ref() const { + throw CanteraError("PDSS_HKFT::cp_RT_ref()", "unimplemented"); + return (0.0); + } + + doublereal + PDSS_HKFT::molarVolume_ref() const { + throw CanteraError("PDSS_HKFT::molarVolume_ref()", "unimplemented"); + return (0.0); + } + + /** + * Calculate the pressure (Pascals), given the temperature and density + * Temperature: kelvin + * rho: density in kg m-3 + */ + doublereal + PDSS_HKFT::pressure() const { + throw CanteraError("PDSS_HKFT::pressure()", "unimplemented"); + return (0.0); + } + + void + PDSS_HKFT::setPressure(doublereal p) { + throw CanteraError("PDSS_HKFT::pressure()", "unimplemented"); + } + + void PDSS_HKFT::setTemperature(doublereal temp) { + m_temp = temp; + } + + doublereal PDSS_HKFT::temperature() const { + return m_temp; + } + + + void PDSS_HKFT::setState_TP(doublereal temp, doublereal pres) { + setTemperature(temp); + setPressure(pres); + } + + /// critical temperature + doublereal + PDSS_HKFT::critTemperature() const { + throw CanteraError("PDSS_HKFT::critTemperature()", "unimplemented"); + return (0.0); + } + + /// critical pressure + doublereal PDSS_HKFT::critPressure() const { + throw CanteraError("PDSS_HKFT::critPressure()", "unimplemented"); + return (0.0); + } + + /// critical density + doublereal PDSS_HKFT::critDensity() const { + throw CanteraError("PDSS_HKFT::critDensity()", "unimplemented"); + return (0.0); + } + + + + + void PDSS_HKFT::initThermo() { + PDSS::initThermo(); + SpeciesThermo &sp = m_tp->speciesThermo(); + m_p0 = sp.refPressure(m_spindex); + + } + + + void PDSS_HKFT::initThermoXML(const XML_Node& phaseNode, std::string id) { + PDSS::initThermoXML(phaseNode, id); + } + + void PDSS_HKFT::constructPDSSXML(VPStandardStateTP *tp, int spindex, + const XML_Node& speciesNode, + const XML_Node& phaseNode, bool spInstalled) { + PDSS::initThermo(); + SpeciesThermo &sp = m_tp->speciesThermo(); + m_p0 = sp.refPressure(m_spindex); + + if (!spInstalled) { + throw CanteraError("PDSS_HKFT::constructPDSSXML", "spInstalled false not handled"); + } + + const XML_Node *ss = speciesNode.findByName("standardState"); + if (!ss) { + throw CanteraError("PDSS_HKFT::constructPDSSXML", + "no standardState Node for species " + speciesNode.name()); + } + std::string model = (*ss)["model"]; + if (model != "constant_incompressible") { + throw CanteraError("PDSS_HKFT::initThermoXML", + "standardState model for species isn't constant_incompressible: " + + speciesNode.name()); + } + + + std::string id = ""; + initThermoXML(phaseNode, id); + } + + void PDSS_HKFT::constructPDSSFile(VPStandardStateTP *tp, int spindex, + std::string inputFile, std::string id) { + + if (inputFile.size() == 0) { + throw CanteraError("PDSS_HKFT::initThermo", + "input file is null"); + } + std::string path = findInputFile(inputFile); + ifstream fin(path.c_str()); + if (!fin) { + throw CanteraError("PDSS_HKFT::initThermo","could not open " + +path+" for reading."); + } + /* + * The phase object automatically constructs an XML object. + * Use this object to store information. + */ + + XML_Node *fxml = new XML_Node(); + fxml->build(fin); + XML_Node *fxml_phase = findXMLPhase(fxml, id); + if (!fxml_phase) { + throw CanteraError("PDSS_HKFT::initThermo", + "ERROR: Can not find phase named " + + id + " in file named " + inputFile); + } + + XML_Node& speciesList = fxml_phase->child("speciesArray"); + XML_Node* speciesDB = get_XML_NameID("speciesData", speciesList["datasrc"], + &(fxml_phase->root())); + const vector&sss = tp->speciesNames(); + const XML_Node* s = speciesDB->findByAttr("name", sss[spindex]); + + constructPDSSXML(tp, spindex, *s, *fxml_phase, true); + delete fxml; + } + +} diff --git a/Cantera/src/thermo/PDSS_HKFT.h b/Cantera/src/thermo/PDSS_HKFT.h new file mode 100644 index 000000000..136dba4c5 --- /dev/null +++ b/Cantera/src/thermo/PDSS_HKFT.h @@ -0,0 +1,416 @@ +/** + * @file PDSS_HKFT.h + * Declarations for the class PDSS_HKFT (pressure dependent standard state) + * which handles calculations for a single species in a phase using the + * HKFT standard state + * (see class \link Cantera::PDSS_HKFT PDSS_HKFT\endlink). + */ +/* $Author$ + * $Date$ + * $Revision$ + * + * + */ + +#ifndef CT_PDSS_HKFT_H +#define CT_PDSS_HKFT_H +#include "ct_defs.h" + + + +class WaterPropsIAPWS; +#include "PDSS.h" + +namespace Cantera { + class XML_Node; + class VPStandardState; + + + //! Class for pressure dependent standard states corresponding to + //! ionic solutes in electrolyte water. + /*! + * + * Virtual base class for calculation of the + * pressure dependent standard state for a single species + * + * Class %PDSS is the base class + * for a family of classes that compute properties of a set of + * species in their standard states at a range of temperatures + * and pressures. The independent variables for this object + * are temperature and pressure. + * The class may mave a reference to a SpeciesThermo object + * which handles the calculation of the reference state temperature + * behavior of a subset of species. + * + * This class is analagous to the SpeciesThermoInterpType + * class, except that the standard state inherently incorporates + * the pressure dependence. + * + * The class operates on a setState temperature and pressure basis. + * It only recalculates the standard state when the setState functions + * for temperature and pressure are called + * + */ + class PDSS_HKFT : public PDSS { + + public: + /** + * @name Constructors + * @{ + */ + + //! Constructor that initializes the object by examining the XML entries + //! from the ThermoPhase object + /*! + * This function calls the constructPDSS member function. + * + * @param tp Pointer to the ThermoPhase object pertaining to the phase + * @param spindex Species index of the species in the phase + */ + PDSS_HKFT(VPStandardStateTP *tp, int spindex); + + //! Copy Constructor + /*! + * @param b object to be copied + */ + PDSS_HKFT(const PDSS_HKFT &b); + + //! Assignment operator + /*! + * @param b Object to be copied + */ + PDSS_HKFT& operator=(const PDSS_HKFT&b); + + //! Constructor that initializes the object by examining the input file + //! of the ThermoPhase object + /*! + * This function calls the constructPDSSFile member function. + * + * @param vptp_ptr Pointer to the ThermoPhase object pertaining to the phase + * @param spindex Species index of the species in the phase + * @param inputFile String name of the input file + * @param id String name of the phase in the input file. The default + * is the empty string, in which case the first phase in the + * file is used. + */ + PDSS_HKFT(VPStandardStateTP *vptp_ptr, int spindex, + std::string inputFile, std::string id = ""); + + //! Constructor that initializes the object by examining the input file + //! of the ThermoPhase object + /*! + * This function calls the constructPDSSXML member function. + * + * @param vptp_ptr Pointer to the ThermoPhase object pertaining to the phase + * @param spindex Species index of the species in the phase + * @param speciesNode Reference to the species XML tree. + * @param phaseRef Reference to the XML tree containing the phase information. + * @param spInstalled Boolean indicating whether the species is installed yet + * or not. + */ + PDSS_HKFT(VPStandardStateTP *vptp_ptr, int spindex, const XML_Node& speciesNode, + const XML_Node& phaseRef, bool spInstalled); + + //! Destructor for the phase + virtual ~PDSS_HKFT(); + + //! Duplicator + virtual PDSS *duplMyselfAsPDSS() const; + + /** + * @} + * @name Utilities + * @{ + */ + virtual int pdssType() const { return -1; } + + /** + * @} + * @name Molar Thermodynamic Properties of the Species Standard State + * in the Solution + * @{ + */ + + /** + * @} + * @name Molar Thermodynamic Properties of the Solution -------------- + * @{ + */ + + //! Return the molar enthalpy in units of J kmol-1 + /*! + * Returns the species standard state enthalpy in J kmol-1 at the + * current temperature and pressure. + * + * @return returns the species standard state enthalpy in J kmol-1 + */ + virtual doublereal enthalpy_mole() const; + + //! Return the standard state molar enthalpy divided by RT + /*! + * Returns the species standard state enthalpy divided by RT at the + * current temperature and pressure. + * + * @return returns the species standard state enthalpy in unitless form + */ + virtual doublereal enthalpy_RT() const; + + //! Return the molar internal Energy in units of J kmol-1 + /*! + * Returns the species standard state internal Energy in J kmol-1 at the + * current temperature and pressure. + * + * @return returns the species standard state internal Energy in J kmol-1 + */ + virtual doublereal intEnergy_mole() const; + + //! Return the molar entropy in units of J kmol-1 K-1 + /*! + * Returns the species standard state entropy in J kmol-1 K-1 at the + * current temperature and pressure. + * + * @return returns the species standard state entropy in J kmol-1 K-1 + */ + virtual doublereal entropy_mole() const; + + //! Return the molar gibbs free energy in units of J kmol-1 + /*! + * Returns the species standard state gibbs free energy in J kmol-1 at the + * current temperature and pressure. + * + * @return returns the species standard state gibbs free energy in J kmol-1 + */ + virtual doublereal gibbs_mole() const; + + //! Return the molar const pressure heat capacity in units of J kmol-1 K-1 + /*! + * Returns the species standard state Cp in J kmol-1 K-1 at the + * current temperature and pressure. + * + * @return returns the species standard state Cp in J kmol-1 K-1 + */ + virtual doublereal cp_mole() const; + + //! Return the molar const volume heat capacity in units of J kmol-1 K-1 + /*! + * Returns the species standard state Cv in J kmol-1 K-1 at the + * current temperature and pressure. + * + * @return returns the species standard state Cv in J kmol-1 K-1 + */ + virtual doublereal cv_mole() const; + + //! Return the molar volume at standard state + /*! + * Returns the species standard state molar volume at the + * current temperature and pressure + * + * @return returns the standard state molar volume divided by R + * units are m**3 kmol-1. + */ + virtual doublereal molarVolume() const; + + /** + * @} + * @name Properties of the Reference State of the Species + * in the Solution + * @{ + */ + + + //! Return the reference pressure for this phase. + doublereal refPressure() const { + return m_p0; + } + + //! Return the molar gibbs free energy divided by RT at reference pressure + /*! + * Returns the species reference state gibbs free energy divided by RT at the + * current temperature. + * + * @return returns the reference state gibbs free energy divided by RT + */ + virtual doublereal gibbs_RT_ref() const; + + //! Return the molar enthalpy divided by RT at reference pressure + /*! + * Returns the species reference state enthalpy divided by RT at the + * current temperature. + * + * @return returns the reference state enthalpy divided by RT + */ + virtual doublereal enthalpy_RT_ref() const; + + //! Return the molar entropy divided by R at reference pressure + /*! + * Returns the species reference state entropy divided by R at the + * current temperature. + * + * @return returns the reference state entropy divided by R + */ + virtual doublereal entropy_R_ref() const; + + //! Return the molar heat capacity divided by R at reference pressure + /*! + * Returns the species reference state heat capacity divided by R at the + * current temperature. + * + * @return returns the reference state heat capacity divided by R + */ + virtual doublereal cp_R_ref() const; + + //! Return the molar volume at reference pressure + /*! + * Returns the species reference state molar volume at the + * current temperature. + * + * @return returns the reference state molar volume divided by R + * units are m**3 kmol-1. + */ + virtual doublereal molarVolume_ref() const; + + /** + * @} + * @name Mechanical Equation of State Properties + * @{ + */ + + //! Returns the pressure (Pa) + virtual doublereal pressure() const; + + //! Sets the pressure in the object + /*! + * Currently, this sets the pressure in the PDSS object. + * It is indeterminant what happens to the owning VPStandardStateTP + * object and to the VPSSMgr object. + * + * @param pres Pressure to be set (Pascal) + */ + virtual void setPressure(doublereal pres); + + //! Set the internal temperature + /*! + * @param temp Temperature (Kelvin) + */ + virtual void setTemperature(doublereal temp); + + //! Return the current storred temperature + doublereal temperature() const; + + //! Set the internal temperature and pressure + /*! + * @param temp Temperature (Kelvin) + * @param pres pressure (Pascals) + */ + virtual void setState_TP(doublereal temp, doublereal pres); + + /** + * @} + * @name Miscellaneous properties of the standard state + * @{ + */ + + /// critical temperature + virtual doublereal critTemperature() const; + + /// critical pressure + virtual doublereal critPressure() const; + + /// critical density + virtual doublereal critDensity() const; + + /** + * @} + * @name Initialization of the Object + * @{ + */ + + //! Initialization routine for all of the shallow pointers + /*! + * This is a cascading call, where each level should call the + * the parent level. + * + * The initThermo() routines get called before the initThermoXML() routines + * from the constructPDSSXML() routine. + * + * + * Calls initPtrs(); + */ + virtual void initThermo(); + + //! Initialization of a PDSS object using an + //! input XML file. + /*! + * + * This routine is a precursor to constructPDSSXML(XML_Node*) + * routine, which does most of the work. + * + * @param vptp_ptr Pointer to the Variable pressure %ThermoPhase object + * This object must have already been malloced. + * + * @param spindex Species index within the phase + * + * @param inputFile 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 constructPDSSFile(VPStandardStateTP *vptp_ptr, int spindex, + std::string inputFile, std::string id); + + //! Initialization of a PDSS object using an xml tree + /*! + * This routine is a driver for the initialization of the + * object. + * + * basic logic: + * initThermo() (cascade) + * getStuff from species Part of XML file + * initThermoXML(phaseNode) (cascade) + * + * @param vptp_ptr Pointer to the Variable pressure %ThermoPhase object + * This object must have already been malloced. + * + * @param spindex Species index within the phase + * + * @param speciesNode XML Node containing the species information + * + * @param phaseNode Reference to the phase Information for the phase + * that owns this species. + * + * @param spInstalled Boolean indicating whether the species is + * already installed. + */ + void constructPDSSXML(VPStandardStateTP *vptp_ptr, int spindex, + const XML_Node& speciesNode, + const XML_Node& phaseNode, bool spInstalled); + + //! Initialization routine for the PDSS object based on the phaseNode + /*! + * This is a cascading call, where each level should call the + * the parent level. + * + * @param phaseNode Reference to the phase Information for the phase + * that owns this species. + * + * @param id Optional parameter identifying the name of the + * phase. If none is given, the first XML + * phase element will be used. + */ + virtual void initThermoXML(const XML_Node& phaseNode, std::string id); + + //@} + + protected: + + + }; + +} + +#endif + + + diff --git a/Cantera/src/thermo/PDSS_IdealGas.cpp b/Cantera/src/thermo/PDSS_IdealGas.cpp new file mode 100644 index 000000000..fabee4196 --- /dev/null +++ b/Cantera/src/thermo/PDSS_IdealGas.cpp @@ -0,0 +1,344 @@ +/** + * @file PDSS_IdealGas.cpp + * Implementation of a pressure dependent standard state + * virtual function. + */ +/* + * Copywrite (2006) Sandia Corporation. Under the terms of + * Contract DE-AC04-94AL85000 with Sandia Corporation, the + * U.S. Government retains certain rights in this software. + */ +/* + * $Id$ + */ + +#include "ct_defs.h" +#include "xml.h" +#include "ctml.h" +#include "PDSS_IdealGas.h" +#include "ThermoFactory.h" + +#include "VPStandardStateTP.h" + +using namespace std; + +namespace Cantera { + /** + * Basic list of constructors and duplicators + */ + + PDSS_IdealGas::PDSS_IdealGas(VPStandardStateTP *tp, int spindex) : + PDSS(tp, spindex) + { + m_pdssType = cPDSS_IDEALGAS; + } + + + PDSS_IdealGas::PDSS_IdealGas(VPStandardStateTP *tp, int spindex, + std::string inputFile, std::string id) : + PDSS(tp, spindex) + { + m_pdssType = cPDSS_IDEALGAS; + constructPDSSFile(tp, spindex, inputFile, id); + } + + + + PDSS_IdealGas::PDSS_IdealGas(VPStandardStateTP *tp, int spindex, const XML_Node& speciesNode, + const XML_Node& phaseRoot, bool spInstalled) : + PDSS(tp, spindex) + { + if (!spInstalled) { + throw CanteraError("PDSS_IdealGas", "sp installing not done yet"); + } + m_pdssType = cPDSS_IDEALGAS; + std::string id = ""; + constructPDSSXML(tp, spindex, phaseRoot, id); + } + + + + PDSS_IdealGas::PDSS_IdealGas(const PDSS_IdealGas &b) : + PDSS(b) + { + /* + * Use the assignment operator to do the brunt + * of the work for the copy construtor. + */ + *this = b; + } + + /** + * Assignment operator + */ + PDSS_IdealGas& PDSS_IdealGas::operator=(const PDSS_IdealGas&b) { + if (&b == this) return *this; + PDSS::operator=(b); + return *this; + } + + PDSS_IdealGas::~PDSS_IdealGas() { + } + + //! Duplicator + PDSS* PDSS_IdealGas::duplMyselfAsPDSS() const { + PDSS_IdealGas * idg = new PDSS_IdealGas(*this); + return (PDSS *) idg; + } + + + + /** + * constructPDSSXML: + * + * Initialization of a PDSS_IdealGas object using an + * xml file. + * + * This routine is a precursor to initThermo(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 PDSS_IdealGas::constructPDSSXML(VPStandardStateTP *tp, int spindex, + const XML_Node& phaseNode, std::string id) { + initThermo(); + initThermoXML(phaseNode, id); + } + + + void PDSS_IdealGas::constructPDSSFile(VPStandardStateTP *tp, int spindex, + std::string inputFile, std::string id) { + + if (inputFile.size() == 0) { + throw CanteraError("PDSS_IdealGas::initThermo", + "input file is null"); + } + std::string path = findInputFile(inputFile); + ifstream fin(path.c_str()); + if (!fin) { + throw CanteraError("PDSS_IdealGas::initThermo","could not open " + +path+" for reading."); + } + /* + * The phase object automatically constructs an XML object. + * Use this object to store information. + */ + + XML_Node *fxml = new XML_Node(); + fxml->build(fin); + XML_Node *fxml_phase = findXMLPhase(fxml, id); + if (!fxml_phase) { + throw CanteraError("PDSS_IdealGas::initThermo", + "ERROR: Can not find phase named " + + id + " in file named " + inputFile); + } + constructPDSSXML(tp, spindex, *fxml_phase, id); + delete fxml; + } + + void PDSS_IdealGas::initThermoXML(const XML_Node& phaseNode, std::string &id) { + PDSS::initThermoXML(phaseNode, id); + } + + void PDSS_IdealGas::initThermo() { + PDSS::initThermo(); + SpeciesThermo &sp = m_tp->speciesThermo(); + m_p0 = sp.refPressure(m_spindex); + } + + /** + * Return the molar enthalpy in units of J kmol-1 + */ + doublereal + PDSS_IdealGas::enthalpy_mole() const { + double val = enthalpy_RT(); + double RT = GasConstant * m_temp; + return (val * RT); + } + + doublereal + PDSS_IdealGas::enthalpy_RT() const { + double val = m_h0_RT_ptr[m_spindex]; + return (val); + } + + + /** + * Calculate the internal energy in mks units of + * J kmol-1 + */ + doublereal + PDSS_IdealGas::intEnergy_mole() const { + double val = m_h0_RT_ptr[m_spindex] - 1.0; + double RT = GasConstant * m_temp; + return (val * RT); + } + + /** + * Calculate the entropy in mks units of + * J kmol-1 K-1 + */ + doublereal + PDSS_IdealGas::entropy_mole() const { + double val = entropy_R(); + return (val * GasConstant); + } + + doublereal + PDSS_IdealGas::entropy_R() const { + double val = m_s0_R_ptr[m_spindex] - log(m_pres/m_p0); + return (val); + } + + /** + * Calculate the Gibbs free energy in mks units of + * J kmol-1 K-1. + */ + doublereal + PDSS_IdealGas::gibbs_mole() const { + double val = gibbs_RT(); + double RT = GasConstant * m_temp; + return (val * RT); + } + + doublereal + PDSS_IdealGas::gibbs_RT() const { + double val = m_g0_RT_ptr[m_spindex] + log(m_pres/m_p0); + return (val); + } + + /** + * Calculate the constant pressure heat capacity + * in mks units of J kmol-1 K-1 + */ + doublereal + PDSS_IdealGas::cp_mole() const { + double val = cp_R(); + return (val * GasConstant); + } + + doublereal + PDSS_IdealGas::cp_R() const { + double val = m_cp0_R_ptr[m_spindex]; + return (val); + } + + doublereal + PDSS_IdealGas::molarVolume() const { + return (GasConstant * m_temp / m_pres); + } + + /** + * Calculate the constant volume heat capacity + * in mks units of J kmol-1 K-1 + */ + doublereal + PDSS_IdealGas::cv_mole() const { + return (cp_mole() - GasConstant); + } + + + doublereal + PDSS_IdealGas::gibbs_RT_ref() const { + double val = m_g0_RT_ptr[m_spindex]; + return (val); + } + + doublereal PDSS_IdealGas::enthalpy_RT_ref() const { + double val = m_h0_RT_ptr[m_spindex]; + return (val); + } + + doublereal PDSS_IdealGas::entropy_R_ref() const { + double val = m_s0_R_ptr[m_spindex]; + return (val); + } + + doublereal PDSS_IdealGas::cp_R_ref() const { + return (cp_R()); + } + + doublereal PDSS_IdealGas::molarVolume_ref() const { + return (GasConstant * m_temp / m_p0); + } + + /** + * Calculate the pressure (Pascals), given the temperature and density + * Temperature: kelvin + * rho: density in kg m-3 + */ + doublereal PDSS_IdealGas::pressure() const { + throw CanteraError("PDSS_IdealGas::pressure()", "unimplemented"); + return (0.0); + } + + void PDSS_IdealGas::setPressure(doublereal p) { + m_sss_R_ptr[m_spindex] = m_s0_R_ptr[m_spindex] + log(m_pres/m_p0); + m_gss_RT_ptr[m_spindex] = m_hss_RT_ptr[m_spindex] - m_sss_R_ptr[m_spindex]; + m_Vss_ptr[m_spindex] = GasConstant * m_temp / m_pres; + } + + + /// critical temperature + doublereal PDSS_IdealGas::critTemperature() const { + throw CanteraError("PDSS_IdealGas::critTemperature()", "unimplemented"); + return (0.0); + } + + /// critical pressure + doublereal PDSS_IdealGas::critPressure() const { + throw CanteraError("PDSS_IdealGas::critPressure()", "unimplemented"); + return (0.0); + } + + /// critical density + doublereal PDSS_IdealGas::critDensity() const { + throw CanteraError("PDSS_IdealGas::critDensity()", "unimplemented"); + return (0.0); + } + + + /** + * Return the temperature + * + * Obtain the temperature from the owning VPStandardStateTP object + * if you can. + */ + double PDSS_IdealGas::temperature() const { + m_temp = m_vpssmgr_ptr->temperature(); + return m_temp; + } + + void PDSS_IdealGas::setTemperature(double temp) { + m_temp = temp; + m_spthermo->update_one(m_spindex, temp, + m_cp0_R_ptr, m_h0_RT_ptr, m_s0_R_ptr); + m_g0_RT_ptr[m_spindex] = m_h0_RT_ptr[m_spindex] - m_s0_R_ptr[m_spindex]; + m_V0_ptr[m_spindex] = GasConstant * m_temp / m_p0; + + m_hss_RT_ptr[m_spindex] = m_h0_RT_ptr[m_spindex]; + m_cpss_R_ptr[m_spindex] = m_cp0_R_ptr[m_spindex]; + m_sss_R_ptr[m_spindex] = m_s0_R_ptr[m_spindex] + log(m_pres/m_p0); + m_gss_RT_ptr[m_spindex] = m_hss_RT_ptr[m_spindex] - m_sss_R_ptr[m_spindex]; + m_Vss_ptr[m_spindex] = GasConstant * m_temp / m_pres; + } + + + void PDSS_IdealGas::setState_TP(double temp, double pres) { + m_pres = pres; + setTemperature(temp); + } + + /// saturation pressure + doublereal PDSS_IdealGas::satPressure(doublereal t){ + throw CanteraError("PDSS_IdealGas::satPressure()", "unimplemented"); + return (0.0); + } + + +} diff --git a/Cantera/src/thermo/PDSS_IdealGas.h b/Cantera/src/thermo/PDSS_IdealGas.h new file mode 100644 index 000000000..d288f4327 --- /dev/null +++ b/Cantera/src/thermo/PDSS_IdealGas.h @@ -0,0 +1,427 @@ +/** + * @file PDSS_IdealGas.h + * Declarations for the class PDSS_IdealGas (pressure dependent standard state) + * which handles calculations for a single ideal gas species in a phase + * (see class \link Cantera::PDSS_IdealGas PDSS_IdealGas\endlink). + */ +/* + * Copywrite (2006) Sandia Corporation. Under the terms of + * Contract DE-AC04-94AL85000 with Sandia Corporation, the + * U.S. Government retains certain rights in this software. + */ +/* + * $Id$ + */ + +#ifndef CT_PDSS_IDEALGAS_H +#define CT_PDSS_IDEALGAS_H + +#include "PDSS.h" + + +namespace Cantera { + class XML_Node; + class VPStandardStateTP; + + /** + * Derived class for pressure dependent standard states. + * This class is for a single Ideal Gas species. + * + */ + class PDSS_IdealGas : public PDSS { + + public: + + /** + * @name Constructors + * @{ + */ + + //! Constructor + /*! + * @param tp Pointer to the ThermoPhase object pertaining to the phase + * @param spindex Species index of the species in the phase + */ + PDSS_IdealGas(VPStandardStateTP *tp, int spindex); + + //! Copy Constructur + /*! + * @param b Object to be copied + */ + PDSS_IdealGas(const PDSS_IdealGas& b); + + //! Assignment operator + /*! + * @param b Object to be copeid + */ + PDSS_IdealGas& operator=(const PDSS_IdealGas& b); + + //! Constructor that initializes the object by examining the input file + //! of the ThermoPhase object + /*! + * This function calls the constructPDSSFile member function. + * + * @param tp Pointer to the ThermoPhase object pertaining to the phase + * @param spindex Species index of the species in the phase + * @param inputFile String name of the input file + * @param id String name of the phase in the input file. The default + * is the empty string, in which case the first phase in the + * file is used. + */ + PDSS_IdealGas(VPStandardStateTP *tp, int spindex, + std::string inputFile, std::string id = ""); + + + //! Constructor that initializes the object by examining the input file + //! of the ThermoPhase object + /*! + * This function calls the constructPDSSXML member function. + * + * @param vptp_ptr Pointer to the ThermoPhase object pertaining to the phase + * @param spindex Species index of the species in the phase + * @param speciesNode Reference to the species XML tree. + * @param phaseRef Reference to the XML tree containing the phase information. + * @param spInstalled Boolean indicating whether the species is installed yet + * or not. + */ + PDSS_IdealGas(VPStandardStateTP *vptp_ptr, int spindex, const XML_Node& speciesNode, + const XML_Node& phaseRef, bool spInstalled); + + + //! Destructor + virtual ~PDSS_IdealGas(); + + //! Duplicator + virtual PDSS *duplMyselfAsPDSS() const; + + /** + * @} + * @name Utilities + * @{ + */ + virtual int pdssType() const { return -1; } + + + /** + * @} + * @name Molar Thermodynamic Properties of the Species Standard State + * in the Solution + * @{ + */ + + //! Return the molar enthalpy in units of J kmol-1 + /*! + * Returns the species standard state enthalpy in J kmol-1 at the + * current temperature and pressure. + * + * @return returns the species standard state enthalpy in J kmol-1 + */ + virtual doublereal enthalpy_mole() const; + + //! Return the standard state molar enthalpy divided by RT + /*! + * Returns the species standard state enthalpy divided by RT at the + * current temperature and pressure. + * + * @return returns the species standard state enthalpy in unitless form + */ + virtual doublereal enthalpy_RT() const; + + //! Return the molar internal Energy in units of J kmol-1 + /*! + * Returns the species standard state internal Energy in J kmol-1 at the + * current temperature and pressure. + * + * @return returns the species standard state internal Energy in J kmol-1 + */ + virtual doublereal intEnergy_mole() const; + + //! Return the molar entropy in units of J kmol-1 K-1 + /*! + * Returns the species standard state entropy in J kmol-1 K-1 at the + * current temperature and pressure. + * + * @return returns the species standard state entropy in J kmol-1 K-1 + */ + virtual doublereal entropy_mole() const; + + //! Return the standard state entropy divided by RT + /*! + * Returns the species standard state entropy divided by RT at the + * current temperature and pressure. + * + * @return returns the species standard state entropy divided by RT + */ + virtual doublereal entropy_R() const; + + //! Return the molar gibbs free energy in units of J kmol-1 + /*! + * Returns the species standard state gibbs free energy in J kmol-1 at the + * current temperature and pressure. + * + * @return returns the species standard state gibbs free energy in J kmol-1 + */ + virtual doublereal gibbs_mole() const; + + //! Return the molar gibbs free energy divided by RT + /*! + * Returns the species standard state gibbs free energy divided by RT at the + * current temperature and pressure. + * + * @return returns the species standard state gibbs free energy divided by RT + */ + virtual doublereal gibbs_RT() const; + + //! Return the molar const pressure heat capacity in units of J kmol-1 K-1 + /*! + * Returns the species standard state Cp in J kmol-1 K-1 at the + * current temperature and pressure. + * + * @return returns the species standard state Cp in J kmol-1 K-1 + */ + virtual doublereal cp_mole() const; + + //! Return the molar const pressure heat capacity divided by RT + /*! + * Returns the species standard state Cp divided by RT at the + * current temperature and pressure. + * + * @return returns the species standard state Cp divided by RT + */ + virtual doublereal cp_R() const; + + //! Return the molar const volume heat capacity in units of J kmol-1 K-1 + /*! + * Returns the species standard state Cv in J kmol-1 K-1 at the + * current temperature and pressure. + * + * @return returns the species standard state Cv in J kmol-1 K-1 + */ + virtual doublereal cv_mole() const; + + //! Return the molar volume at standard state + /*! + * Returns the species standard state molar volume at the + * current temperature and pressure + * + * @return returns the standard state molar volume divided by R + * units are m**3 kmol-1. + */ + virtual doublereal molarVolume() const; + + /** + * @} + * @name Properties of the Reference State of the Species + * in the Solution + * @{ + */ + + //! Return the molar gibbs free energy divided by RT at reference pressure + /*! + * Returns the species reference state gibbs free energy divided by RT at the + * current temperature. + * + * @return returns the reference state gibbs free energy divided by RT + */ + virtual doublereal gibbs_RT_ref() const; + + //! Return the molar enthalpy divided by RT at reference pressure + /*! + * Returns the species reference state enthalpy divided by RT at the + * current temperature. + * + * @return returns the reference state enthalpy divided by RT + */ + virtual doublereal enthalpy_RT_ref() const; + + //! Return the molar entropy divided by R at reference pressure + /*! + * Returns the species reference state entropy divided by R at the + * current temperature. + * + * @return returns the reference state entropy divided by R + */ + virtual doublereal entropy_R_ref() const; + + //! Return the molar heat capacity divided by R at reference pressure + /*! + * Returns the species reference state heat capacity divided by R at the + * current temperature. + * + * @return returns the reference state heat capacity divided by R + */ + virtual doublereal cp_R_ref() const; + + //! Return the molar volume at reference pressure + /*! + * Returns the species reference state molar volume at the + * current temperature. + * + * @return returns the reference state molar volume divided by R + * units are m**3 kmol-1. + */ + virtual doublereal molarVolume_ref() const; + + /* + * Get the difference in the standard state thermodynamic properties + * between the reference pressure, po, and the current pressure. + */ + + /** + * @} + * @name Mechanical Equation of State Properties + * @{ + */ + + //! Returns the pressure (Pa) + virtual doublereal pressure() const; + + //! Sets the pressure in the object + /*! + * Currently, this sets the pressure in the PDSS object. + * It is indeterminant what happens to the owning VPStandardStateTP + * object and to the VPSSMgr object. + * + * @param pres Pressure to be set (Pascal) + */ + virtual void setPressure(doublereal pres); + + //! Returns the density of the species + double density() const; + + //! Set the internal temperature + /*! + * @param temp Temperature (Kelvin) + */ + virtual void setTemperature(double temp); + + //! Return the current storred temperature + double temperature() const; + + //! Set the internal temperature and pressure + /*! + * @param temp Temperature (Kelvin) + * @param pres pressure (Pascals) + */ + virtual void setState_TP(double temp, double pres); + + /** + * @} + * @name Miscellaneous properties of the standard state + * @{ + */ + + /// critical temperature + virtual doublereal critTemperature() const; + + /// critical pressure + virtual doublereal critPressure() const; + + /// critical density + virtual doublereal critDensity() const; + + /// saturation pressure + /*! + * @param t Temperature (Kelvin) + */ + virtual doublereal satPressure(doublereal t); + + /** + * @} + * @name Initialization of the Object + * @{ + */ + + //! Initialization of a PDSS object using an + //! input XML file. + /*! + * + * This routine is a precursor to constructPDSSXML(XML_Node*) + * routine, which does most of the work. + * + * @param vptp_ptr Pointer to the Variable pressure %ThermoPhase object + * This object must have already been malloced. + * + * @param spindex Species index within the phase + * + * @param inputFile 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 constructPDSSFile(VPStandardStateTP *vptp_ptr, int spindex, + std::string inputFile, std::string id); + + //!Initialization of a PDSS object using an xml tree + /*! + * This routine is a driver for the initialization of the + * object. + * + * basic logic: + * initThermo() (cascade) + * getStuff from species Part of XML file + * initThermoXML(phaseNode) (cascade) + * + * @param vptp_ptr Pointer to the Variable pressure %ThermoPhase object + * This object must have already been malloced. + * + * @param spindex Species index within the phase + * + * @param phaseNode Reference to the phase Information for the phase + * that owns this species. + * + * @param id Optional parameter identifying the name of the + * phase. If none is given, the first XML + * phase element will be used. + */ + void constructPDSSXML(VPStandardStateTP *vptp_ptr, int spindex, + const XML_Node& phaseNode, std::string id); + + //! Initialization routine for the PDSS object based on the phaseNode + /*! + * This is a cascading call, where each level should call the + * the parent level. + * + * @param phaseNode Reference to the phase Information for the phase + * that owns this species. + * + * @param id Optional parameter identifying the name of the + * phase. If none is given, the first XML + * phase element will be used. + */ + virtual void initThermoXML(const XML_Node& phaseNode, std::string& id); + + //! Initialization routine for all of the shallow pointers + /*! + * This is a cascading call, where each level should call the + * the parent level. + * + * The initThermo() routines get called before the initThermoXML() routines + * from the constructPDSSXML() routine. + * + * + * Calls initPtrs(); + */ + virtual void initThermo(); + + //@} + + + + protected: + + //! Maximum temperature the standard states are good for + doublereal m_tmin; + + //! Minimum temperature the standard states are good for + doublereal m_tmax; + + }; +} + +#endif + + + diff --git a/Cantera/src/thermo/PDSS_Water.cpp b/Cantera/src/thermo/PDSS_Water.cpp new file mode 100644 index 000000000..b336f42ca --- /dev/null +++ b/Cantera/src/thermo/PDSS_Water.cpp @@ -0,0 +1,472 @@ +/** + * @file PDSS_Water.cpp + * + */ +/* + * Copywrite (2006) Sandia Corporation. Under the terms of + * Contract DE-AC04-94AL85000 with Sandia Corporation, the + * U.S. Government retains certain rights in this software. + */ +/* + * $Id$ + */ +#include "ct_defs.h" +#include "xml.h" +#include "ctml.h" +#include "PDSS_Water.h" +#include "WaterPropsIAPWS.h" +//#include "importCTML.h" +#include "ThermoFactory.h" +#include + + +#include "VPStandardStateTP.h" + +namespace Cantera { + /** + * Basic list of constructors and duplicators + */ + PDSS_Water::PDSS_Water() : + PDSS(), + m_sub(0), + m_temp(0.0), + m_dens(1000.0), + m_iState(-3000), + EW_Offset(0.0), + SW_Offset(0.0), + m_verbose(0), + m_allowGasPhase(false) + { + m_pdssType = cPDSS_WATER; + m_sub = new WaterPropsIAPWS(); + m_spthermo = 0; + constructSet(); + } + + PDSS_Water::PDSS_Water(VPStandardStateTP *tp, int spindex) : + PDSS(tp, spindex), + m_sub(0), + m_temp(0.0), + m_dens(1000.0), + m_iState(-3000), + EW_Offset(0.0), + SW_Offset(0.0), + m_verbose(0), + m_allowGasPhase(false) + { + m_pdssType = cPDSS_WATER; + m_sub = new WaterPropsIAPWS(); + m_spthermo = 0; + constructSet(); + } + + + PDSS_Water::PDSS_Water(VPStandardStateTP *tp, int spindex, + std::string inputFile, std::string id) : + PDSS(tp, spindex), + m_sub(0), + m_temp(0.0), + m_dens(1000.0), + m_iState(-3000), + EW_Offset(0.0), + SW_Offset(0.0), + m_verbose(0), + m_allowGasPhase(false) + { + m_pdssType = cPDSS_WATER; + m_sub = new WaterPropsIAPWS(); + constructPDSSFile(tp, spindex, inputFile, id); + m_spthermo = 0; + } + + PDSS_Water::PDSS_Water(VPStandardStateTP *tp, int spindex, + const XML_Node& speciesNode, + const XML_Node& phaseRoot, bool spInstalled) : + PDSS(tp, spindex), + m_sub(0), + m_temp(0.0), + m_dens(1000.0), + m_iState(-3000), + EW_Offset(0.0), + SW_Offset(0.0), + m_verbose(0), + m_allowGasPhase(false) + { + m_pdssType = cPDSS_WATER; + m_sub = new WaterPropsIAPWS(); + std::string id= ""; + constructPDSSXML(tp, spindex, phaseRoot, id) ; + initThermo(); + m_spthermo = 0; + } + + + + PDSS_Water::PDSS_Water(const PDSS_Water &b) : + PDSS(), + m_sub(0), + m_temp(0.0), + m_dens(1000.0), + m_iState(-3000), + EW_Offset(b.EW_Offset), + SW_Offset(b.SW_Offset), + m_verbose(b.m_verbose), + m_allowGasPhase(b.m_allowGasPhase) + { + m_sub = new WaterPropsIAPWS(); + /* + * Use the assignment operator to do the brunt + * of the work for the copy construtor. + */ + *this = b; + } + + /** + * Assignment operator + */ + PDSS_Water& PDSS_Water::operator=(const PDSS_Water&b) { + if (&b == this) return *this; + /* + * Call the base class operator + */ + PDSS::operator=(b); + + m_sub->operator=(*(b.m_sub)); + m_temp = b.m_temp; + m_dens = b.m_dens; + m_iState = b.m_iState; + EW_Offset = b.EW_Offset; + SW_Offset = b.SW_Offset; + m_verbose = b.m_verbose; + m_allowGasPhase = b.m_allowGasPhase; + return *this; + } + + PDSS_Water::~PDSS_Water() { + delete m_sub; + } + + PDSS *PDSS_Water::duplMyselfAsPDSS() const { + PDSS_Water *kPDSS = new PDSS_Water(*this); + return (PDSS *) kPDSS; + } + + /** + * constructPDSSXML: + * + * Initialization of a Debye-Huckel phase using an + * xml file. + * + * This routine is a precursor to initThermo(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 PDSS_Water::constructPDSSXML(VPStandardStateTP *tp, int spindex, + const XML_Node& phaseNode, std::string id) { + constructSet(); + } + + /** + * constructPDSSFile(): + * + * Initialization of a Debye-Huckel phase using an + * xml file. + * + * This routine is a precursor to initThermo(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 PDSS_Water::constructPDSSFile(VPStandardStateTP *tp, int spindex, + std::string inputFile, std::string id) { + + if (inputFile.size() == 0) { + throw CanteraError("aterTp::initThermo", + "input file is null"); + } + std::string path = findInputFile(inputFile); + std::ifstream fin(path.c_str()); + if (!fin) { + throw CanteraError("PDSS_Water::initThermo","could not open " + +path+" for reading."); + } + /* + * The phase object automatically constructs an XML object. + * Use this object to store information. + */ + + XML_Node *fxml = new XML_Node(); + fxml->build(fin); + XML_Node *fxml_phase = findXMLPhase(fxml, id); + if (!fxml_phase) { + throw CanteraError("PDSS_Water::initThermo", + "ERROR: Can not find phase named " + + id + " in file named " + inputFile); + } + constructPDSSXML(tp, spindex, *fxml_phase, id); + delete fxml; + } + + + + void PDSS_Water::constructSet() { + if (m_sub) delete m_sub; + m_sub = new WaterPropsIAPWS(); + if (m_sub == 0) { + throw CanteraError("PDSS_Water::initThermo", + "could not create new substance object."); + } + /* + * Calculate the molecular weight. + * hard coded to Cantera's elements and Water. + */ + m_mw = 2 * 1.00794 + 15.9994; + + /* + * Set the baseline + */ + doublereal T = 298.15; + + m_p0 = OneAtm; + + doublereal presLow = 1.0E-2; + doublereal oneBar = 1.0E5; + doublereal dens = 1.0E-9; + doublereal dd = m_sub->density(T, presLow, WATER_GAS, dens); + setTemperature(T); + m_dens = dd; + SW_Offset = 0.0; + doublereal s = entropy_mole(); + s -= GasConstant * log(oneBar/presLow); + if (s != 188.835E3) { + SW_Offset = 188.835E3 - s; + } + s = entropy_mole(); + s -= GasConstant * log(oneBar/presLow); + //printf("s = %g\n", s); + + doublereal h = enthalpy_mole(); + if (h != -241.826E6) { + EW_Offset = -241.826E6 - h; + } + h = enthalpy_mole(); + + //printf("h = %g\n", h); + + + /* + * Set the initial state of the system to 298.15 K and + * 1 bar. + */ + setTemperature(298.15); + doublereal rho0 = m_sub->density(298.15, OneAtm, WATER_LIQUID); + m_dens = rho0; + } + + void PDSS_Water::initThermo() { + PDSS::initThermo(); + } + + void PDSS_Water:: + initThermoXML(const XML_Node& phaseNode, std::string id) { + PDSS::initThermoXML(phaseNode, id); + } + + doublereal PDSS_Water:: + enthalpy_mole() const { + doublereal T = m_temp; + doublereal dens = m_dens; + doublereal h = m_sub->enthalpy(T, dens); + return (h + EW_Offset); + } + + doublereal PDSS_Water:: + intEnergy_mole() const { + doublereal T = m_dens; + doublereal dens = m_temp; + doublereal u = m_sub->intEnergy(T, dens); + return (u + EW_Offset); + } + + doublereal PDSS_Water:: + entropy_mole() const { + doublereal T = m_temp; + doublereal dens = m_dens; + doublereal s = m_sub->entropy(T, dens); + return (s + SW_Offset); + } + + + doublereal PDSS_Water:: + gibbs_mole() const { + doublereal T = m_temp; + doublereal dens = m_dens; + doublereal g = m_sub->Gibbs(T, dens); + return (g + EW_Offset - SW_Offset*T); + } + + + doublereal PDSS_Water:: + cp_mole() const { + doublereal T = m_temp; + doublereal dens = m_dens; + doublereal cp = m_sub->cp(T, dens); + return cp; + } + + + doublereal PDSS_Water:: + cv_mole() const { + doublereal T = m_temp; + doublereal dens = m_dens; + doublereal cv = m_sub->cv(T, dens); + return cv; + } + + doublereal + PDSS_Water::molarVolume() const { + doublereal T = m_temp; + doublereal dens = m_dens; + doublereal mv = m_sub->molarVolume(T, dens); + return (mv); + } + + doublereal + PDSS_Water::gibbs_RT_ref() const { + doublereal T = m_temp; + doublereal dens0 = m_sub->density(T, m_p0); + doublereal h = m_sub->enthalpy(T, dens0); + m_sub->setState(m_temp, m_dens); + return ((h + EW_Offset - SW_Offset*T)/(T * GasConstant)); + } + + + doublereal + PDSS_Water::enthalpy_RT_ref() const { + doublereal T = m_temp; + doublereal dens0 = m_sub->density(T, m_p0); + doublereal h = m_sub->enthalpy(T, dens0); + m_sub->setState(m_temp, m_dens); + return ((h + EW_Offset)/(T * GasConstant)); + } + + doublereal PDSS_Water:: + entropy_R_ref() const { + doublereal T = m_temp; + doublereal dens0 = m_sub->density(T, m_p0); + doublereal s = m_sub->entropy(T, dens0); + m_sub->setState(m_temp, m_dens); + return ((s + SW_Offset)/GasConstant); + } + + doublereal PDSS_Water:: + cp_R_ref() const { + doublereal T = m_temp; + doublereal dens0 = m_sub->density(T, m_p0); + doublereal cp = m_sub->cp(T, dens0); + m_sub->setState(m_temp, m_dens); + return (cp/GasConstant); + } + + doublereal PDSS_Water:: + molarVolume_ref() const { + doublereal T = m_temp; + doublereal dens0 = m_sub->density(T, m_p0); + doublereal mv = m_sub->molarVolume(T, dens0); + m_sub->setState(m_temp, m_dens); + return (mv); + } + + + /** + * Calculate the pressure (Pascals), given the temperature and density + * Temperature: kelvin + * rho: density in kg m-3 + */ + doublereal PDSS_Water:: + pressure() const { + doublereal T = m_temp; + doublereal dens = m_dens; + doublereal p = m_sub->pressure(T, dens); + m_pres = p; + return p; + } + + + void PDSS_Water:: + setPressure(doublereal p) { + doublereal T = m_temp; + doublereal dens = m_dens; + int waterState = WATER_GAS; + doublereal rc = m_sub->Rhocrit(); + if (dens > rc) { + waterState = WATER_LIQUID; + } +#ifdef DEBUG_HKM + //printf("waterPDSS: set pres = %g t = %g, waterState = %d\n", + // p, T, waterState); +#endif + doublereal dd = m_sub->density(T, p, waterState, dens); + if (dd <= 0.0) { + std::string stateString = "T = " + + fp2str(T) + " K and p = " + fp2str(p) + " Pa"; + throw CanteraError("PDSS_Water:setPressure()", + "Failed to set water SS state: " + stateString); + } + m_dens = dd; + m_pres = p; + } + + + /// critical temperature + doublereal PDSS_Water::critTemperature() const { return m_sub->Tcrit(); } + + /// critical pressure + doublereal PDSS_Water::critPressure() const { return m_sub->Pcrit(); } + + /// critical density + doublereal PDSS_Water::critDensity() const { return m_sub->Rhocrit(); } + + void PDSS_Water::setDensity(doublereal dens) { + m_dens = dens; + m_sub->setState(m_temp, m_dens); + } + + doublereal PDSS_Water::density() const { + return m_dens; + } + + void PDSS_Water::setTemperature(doublereal temp) { + m_temp = temp; + doublereal dd = m_dens; + m_sub->setState(temp, dd); + } + + void PDSS_Water::setState_TP(doublereal temp, doublereal pres) { + m_temp = temp; + setPressure(pres); + } + + /// saturation pressure + doublereal PDSS_Water::satPressure(doublereal t){ + doublereal pp = m_sub->psat(t); + doublereal dens = m_dens; + m_temp = t; + m_dens = dens; + return pp; + } + + + +} diff --git a/Cantera/src/thermo/PDSS_Water.h b/Cantera/src/thermo/PDSS_Water.h new file mode 100644 index 000000000..e229a0432 --- /dev/null +++ b/Cantera/src/thermo/PDSS_Water.h @@ -0,0 +1,498 @@ +/** + * @file PDSS_Water.h + * Implementation of a pressure dependent standard state + * virtual function for a Pure Water Phase + * (see class \link Cantera::PDSS_Water PDSS_Water\endlink). + */ +/* + * Copywrite (2006) 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$ + */ + +#ifndef CT_WATERPDSS_H +#define CT_WATERPDSS_H +#include "ct_defs.h" +#include "PDSS.h" +#include "VPStandardStateTP.h" + +class WaterPropsIAPWS; + +namespace Cantera { + + //! Class for the liquid water pressure dependent + //! standard state + /*! + * + * Notes: + * Base state for thermodynamic properties: + * + * The thermodynamic base state for water is set to the NIST basis here + * by specifying constants EW_Offset and SW_Offset. These offsets are + * specified so that the following properties hold: + * + * Delta_Hfo_gas(298.15) = -241.826 kJ/gmol + * So_gas(298.15, 1bar) = 188.835 J/gmolK + * + * (http://webbook.nist.gov) + * + * The "o" here refers to a hypothetical ideal gas state. The way + * we achieve this in practice is to evaluate at a very low pressure + * and then use the theoretical ideal gas results to scale up to + * higher pressures: + * + * Ho(1bar) = H(P0) + * + * So(1bar) = S(P0) + RT ln(1bar/P0) + * + * The offsets used in the steam tables are different than NIST's. + * They assume u_liq(TP) = 0.0, s_liq(TP) = 0.0, where TP is the + * triple point conditions. + * + */ + class PDSS_Water : public PDSS { + + public: + + /** + * @name Constructors + * @{ + */ + + //! Bare constructor + /*! + * eliminate? + */ + PDSS_Water(); + + //! Constructor that initializes the object by examining the XML entries + //! from the ThermoPhase object + /*! + * This function calls the constructPDSS member function. + * + * @param tp Pointer to the ThermoPhase object pertaining to the phase + * @param spindex Species index of the species in the phase + */ + PDSS_Water(VPStandardStateTP *tp, int spindex); + + //! Copy Constructor + /*! + * @param b object to be copied + */ + PDSS_Water(const PDSS_Water &b); + + //! Assignment operator + /*! + * @param b Object to be copied + */ + PDSS_Water& operator=(const PDSS_Water& b); + + //! Constructor that initializes the object by examining the input file + //! of the variable pressure ThermoPhase object + /*! + * This function calls the constructPDSSFile member function. + * + * @param tp Pointer to the variable pressure ThermoPhase object pertaining to the phase + * @param spindex Species index of the species in the phase + * @param inputFile String name of the input file + * @param id String name of the phase in the input file. The default + * is the empty string, in which case the first phase in the + * file is used. + */ + PDSS_Water(VPStandardStateTP *tp, int spindex, + std::string inputFile, std::string id = ""); + + //! Constructor that initializes the object by examining the input file + //! of the variable pressure ThermoPhase object + /*! + * This function calls the constructPDSSXML member function. + * + * @param tp Pointer to the ThermoPhase object pertaining to the phase + * @param spindex Species index of the species in the phase + * @param speciesNode Reference to the species XML tree. + * @param phaseRef Reference to the XML tree containing the phase information. + * @param spInstalled Is the species already installed. + */ + PDSS_Water(VPStandardStateTP *tp, int spindex, const XML_Node& speciesNode, + const XML_Node& phaseRef, bool spInstalled); + + //! Destructor + virtual ~PDSS_Water(); + + //! Duplication routine for objects which inherit from %PDSS + /*! + * This virtual routine can be used to duplicate %PDSS objects + * inherited from %PDSS even if the application only has + * a pointer to %PDSS to work with. + * + * @return returns a pointer to the base %PDSS object type + */ + virtual PDSS *duplMyselfAsPDSS() const; + + /** + * @} + * @name Utilities + * @{ + */ + + //! Returns the type of the standard state parameterization + /*! + * @return Returns the integer # of the parameterization + */ + virtual PDSS_enumType reportPDSSType() const { return cPDSS_WATER; } + + /** + * @} + * @name Molar Thermodynamic Properties of the Species Standard State + * in the Solution + * @{ + */ + + //! Return the molar enthalpy in units of J kmol-1 + /*! + * Returns the species standard state enthalpy in J kmol-1 at the + * current temperature and pressure. + * + * @return returns the species standard state enthalpy in J kmol-1 + */ + virtual doublereal enthalpy_mole() const; + + //! Return the molar internal Energy in units of J kmol-1 + /*! + * Returns the species standard state internal Energy in J kmol-1 at the + * current temperature and pressure. + * + * @return returns the species standard state internal Energy in J kmol-1 + */ + virtual doublereal intEnergy_mole() const; + + //! Return the molar entropy in units of J kmol-1 K-1 + /*! + * Returns the species standard state entropy in J kmol-1 K-1 at the + * current temperature and pressure. + * + * @return returns the species standard state entropy in J kmol-1 K-1 + */ + virtual doublereal entropy_mole() const; + + //! Return the molar gibbs free energy in units of J kmol-1 + /*! + * Returns the species standard state gibbs free energy in J kmol-1 at the + * current temperature and pressure. + * + * @return returns the species standard state gibbs free energy in J kmol-1 + */ + virtual doublereal gibbs_mole() const; + + //! Return the molar const pressure heat capacity in units of J kmol-1 K-1 + /*! + * Returns the species standard state Cp in J kmol-1 K-1 at the + * current temperature and pressure. + * + * @return returns the species standard state Cp in J kmol-1 K-1 + */ + virtual doublereal cp_mole() const; + + //! Return the molar const volume heat capacity in units of J kmol-1 K-1 + /*! + * Returns the species standard state Cv in J kmol-1 K-1 at the + * current temperature and pressure. + * + * @return returns the species standard state Cv in J kmol-1 K-1 + */ + virtual doublereal cv_mole() const; + + //! Return the molar volume at standard state + /*! + * Returns the species standard state molar volume at the + * current temperature and pressure + * + * @return returns the standard state molar volume divided by R + * units are m**3 kmol-1. + */ + virtual doublereal molarVolume() const; + + /** + * @} + * @name Properties of the Reference State of the Species + * in the Solution + * @{ + */ + + //! Return the molar gibbs free energy divided by RT at reference pressure + /*! + * Returns the species reference state gibbs free energy divided by RT at the + * current temperature. + * + * @return returns the reference state gibbs free energy divided by RT + */ + virtual doublereal gibbs_RT_ref() const; + + //! Return the molar enthalpy divided by RT at reference pressure + /*! + * Returns the species reference state enthalpy divided by RT at the + * current temperature. + * + * @return returns the reference state enthalpy divided by RT + */ + virtual doublereal enthalpy_RT_ref() const; + + //! Return the molar entropy divided by R at reference pressure + /*! + * Returns the species reference state entropy divided by R at the + * current temperature. + * + * @return returns the reference state entropy divided by R + */ + virtual doublereal entropy_R_ref() const; + + //! Return the molar heat capacity divided by R at reference pressure + /*! + * Returns the species reference state heat capacity divided by R at the + * current temperature. + * + * @return returns the reference state heat capacity divided by R + */ + virtual doublereal cp_R_ref() const; + + //! Return the molar volume at reference pressure + /*! + * Returns the species reference state molar volume at the + * current temperature. + * + * @return returns the reference state molar volume divided by R + * units are m**3 kmol-1. + */ + virtual doublereal molarVolume_ref() const;\ + + /** + * @} + * @name Mechanical Equation of State Properties + * @{ + */ + + + //! Report the current pressure used in the object + /*! + * @return Returns the pressure (Pascal) + */ + virtual doublereal pressure() const; + + //! Set the pressure internally + /*! + * @param pres Value of the pressure (Pascals) + */ + virtual void setPressure(doublereal pres); + + //! Set the internal temperature + /*! + * @param temp Temperature (Kelvin) + */ + virtual void setTemperature(doublereal temp); + + //! Set the temperature and pressure in the object + /*! + * @param temp Temperature (Kelvin) + * @param pres Pressure (Pascal) + */ + virtual void setState_TP(doublereal temp, doublereal pres); + + //! Set the density of the water phase + /*! + * This is a non-virtual function because it specific + * to this object. + * + * @param dens Density of the water (kg/m3) + */ + void setDensity(doublereal dens); + + //! Report the current density of the water + /*! + * This is a non-virtual function because it specific + * to this object. + */ + doublereal density() const; + + /** + * @} + * @name Miscellaneous properties of the standard state + * @{ + */ + + //! critical temperature + virtual doublereal critTemperature() const; + + //! critical pressure + virtual doublereal critPressure() const; + + //! critical density + virtual doublereal critDensity() const; + + //! Return the saturation pressure at a given temperature + /*! + * @param t Temperature (Kelvin) + */ + virtual doublereal satPressure(doublereal t); + + //! Get a pointer to the WaterPropsIAPWS object + WaterPropsIAPWS *getWater() const { + return m_sub; + } + + /** + * @} + * @name Initialization of the Object + * @{ + */ + + //! Internal routine that initializes the underlying water model + /*! + * This routine is not virtual + */ + void constructSet(); + + //! Initialization of a PDSS object using an + //! input XML file. + /*! + * + * This routine is a precursor to constructPDSSXML(XML_Node*) + * routine, which does most of the work. + * + * @param vptp_ptr Pointer to the Variable pressure %ThermoPhase object + * This object must have already been malloced. + * + * @param spindex Species index within the phase + * + * @param inputFile 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 constructPDSSFile(VPStandardStateTP *vptp_ptr, int spindex, + std::string inputFile, std::string id); + + //!Initialization of a PDSS object using an xml tree + /*! + * This routine is a driver for the initialization of the + * object. + * + * basic logic: + * initThermo() (cascade) + * getStuff from species Part of XML file + * initThermoXML(phaseNode) (cascade) + * + * @param vptp_ptr Pointer to the Variable pressure %ThermoPhase object + * This object must have already been malloced. + * + * @param spindex Species index within the phase + * + * @param phaseNode Reference to the phase Information for the phase + * that owns this species. + * + * @param id Optional parameter identifying the name of the + * phase. If none is given, the first XML + * phase element will be used. + */ + void constructPDSSXML(VPStandardStateTP *vptp_ptr, int spindex, + const XML_Node& phaseNode, std::string id); + + //! Initialization routine for all of the shallow pointers + /*! + * This is a cascading call, where each level should call the + * the parent level. + * + * The initThermo() routines get called before the initThermoXML() routines + * from the constructPDSSXML() routine. + * + * + * Calls initPtrs(); + */ + virtual void initThermo(); + + //! Initialization routine for the PDSS object based on the phaseNode + /*! + * This is a cascading call, where each level should call the + * the parent level. + * + * @param phaseNode Reference to the phase Information for the phase + * that owns this species. + * + * @param id Optional parameter identifying the name of the + * phase. If none is given, the first XML + * phase element will be used. + */ + virtual void initThermoXML(const XML_Node& phaseNode, std::string id); + + + //@} + + protected: + + + private: + + //! Pointer to the WaterProps object, which does the actual calculations + //! for the real equation of state + /*! + * This object owns m_sub + */ + mutable WaterPropsIAPWS *m_sub; + + /** + * state of the system (temperature and density); + */ + doublereal m_temp; + + //! State of the system - density + /*! + * Density is the independent variable here, but it's hidden behind the + * object's interface. + */ + doublereal m_dens; + + //! state of the fluid + /*! + * 0 gas + * 1 liquid + * 2 supercrit + */ + int m_iState; + + /** + * Offset constants used to obtain consistency with the NIST database. + * This is added to all internal energy and enthalpy results. + * units = J kmol-1. + */ + doublereal EW_Offset; + + /** + * Offset constant used to obtain consistency with NIST convention. + * This is added to all internal entropy results. + * units = J kmol-1 K-1. + */ + doublereal SW_Offset; + + //! Verbose flag - used? + bool m_verbose; + + /** + * Since this phase represents a liquid phase, it's an error to + * return a gas-phase answer. However, if the below is true, then + * a gas-phase answer is allowed. This is used to check the thermodynamic + * consistency with ideal-gas thermo functions for example. + */ + bool m_allowGasPhase; + }; + +} + +#endif + + + diff --git a/Cantera/src/thermo/SpeciesThermo.h b/Cantera/src/thermo/SpeciesThermo.h index 085801ac5..a6ad777cb 100755 --- a/Cantera/src/thermo/SpeciesThermo.h +++ b/Cantera/src/thermo/SpeciesThermo.h @@ -1,10 +1,8 @@ /** * @file SpeciesThermo.h * Virtual base class for the calculation of multiple-species thermodynamic - * property managers and text for the spthermo module (see \ref spthermo + * reference-state 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 ) */ /* @@ -26,7 +24,7 @@ namespace Cantera { class SpeciesThermoInterpType; /** - * @defgroup spthermo Species Standard-State Thermodynamic Properties + * @defgroup spthermo Species Reference-State Thermodynamic Properties * * To compute the thermodynamic properties of multicomponent * solutions, it is necessary to know something about the @@ -35,8 +33,8 @@ namespace Cantera { * 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 + * the mixture temperature and at a reference pressure (almost always at + * 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 @@ -44,13 +42,13 @@ namespace Cantera { * 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 + * data for the solutes in the limit of infinite dilution within 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 + * of a species in a phase limited to one particular 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 @@ -67,12 +65,13 @@ namespace Cantera { * 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. + * calculates the reference-state 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. + * The following classes inherit from SpeciesThermo. Each of these classes + * handle multiple species, usually all of the species in a phas. However, + * there is no requirement that a %SpeciesThermo object handles 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 @@ -98,7 +97,8 @@ namespace Cantera { * 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 + * 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. @@ -131,7 +131,17 @@ namespace Cantera { * - This is a multiple zone model, consisting of the 9 * coefficient Nasa Polynomial format in each zone. * . - * . + * .In particular the NasaThermo %SpeciesThermo-derived model has + * been optimized for execution speed. It's the main-stay of + * gas phase computations involving large numbers of species in + * a phase. It combines the calculation of each species, which + * individually have NasaPoly2 representations, to + * minimize the computational time. + * + * The GeneralSpeciesThermo %SpeciesThermo object is completely + * general. It does not try to coordinate the individual species + * calculations at all and therefore is the slowest but + * most general implementation. * * @ingroup phases */ diff --git a/Cantera/src/thermo/SpeciesThermoFactory.cpp b/Cantera/src/thermo/SpeciesThermoFactory.cpp index bbe2c1959..a2100229c 100755 --- a/Cantera/src/thermo/SpeciesThermoFactory.cpp +++ b/Cantera/src/thermo/SpeciesThermoFactory.cpp @@ -32,6 +32,8 @@ using namespace std; #include "SpeciesThermoMgr.h" #include "speciesThermoTypes.h" +#include "VPSSMgr.h" +#include "VPStandardStateTP.h" #include "xml.h" #include "ctml.h" @@ -117,17 +119,17 @@ namespace Cantera { 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); + getSpeciesThermoTypes(spData_nodes[j], inasa, ishomate, isimple, iother); } catch (UnknownSpeciesThermoModel) { - iother = 1; - popError(); + iother = 1; + popError(); } } if (iother) { return new GeneralSpeciesThermo(); } return newSpeciesThermo(NASA*inasa - + SHOMATE*ishomate + SIMPLE*isimple); + + SHOMATE*ishomate + SIMPLE*isimple); } @@ -307,7 +309,7 @@ namespace Cantera { * parameterization for species k into a SpeciesThermo instance. */ static void installNasa96ThermoFromXML(std::string speciesName, - SpeciesThermo& sp, int k, + SpeciesThermo& sp, int k, const XML_Node* f0ptr, const XML_Node* f1ptr) { doublereal tmin0, tmax0, tmin1, tmax1, tmin, tmid, tmax; @@ -367,7 +369,7 @@ namespace Cantera { * parameterization for species k. */ static void installShomateThermoFromXML(std::string speciesName, - SpeciesThermo& sp, int k, + SpeciesThermo& sp, int k, const XML_Node* f0ptr, const XML_Node* f1ptr) { doublereal tmin0, tmax0, tmin1, tmax1, tmin, tmid, tmax; @@ -422,7 +424,7 @@ namespace Cantera { * parameterization for species k. */ static void installSimpleThermoFromXML(std::string speciesName, - SpeciesThermo& sp, int k, + SpeciesThermo& sp, int k, const XML_Node& f) { doublereal tmin, tmax; tmin = fpValue(f["Tmin"]); @@ -572,7 +574,7 @@ namespace Cantera { } #ifdef WITH_ADSORBATE else if (f->name() == "adsorbate") { - installAdsorbateThermoFromXML(s["name"], spthermo, k, *f); + installAdsorbateThermoFromXML(s["name"], spthermo, k, *f); } #endif else { @@ -606,9 +608,22 @@ namespace Cantera { "multiple"); } } else { - throw UnknownSpeciesThermoModel("installThermoForSpecies", s["name"], - "multiple"); - } + throw UnknownSpeciesThermoModel("installThermoForSpecies", s["name"], + "multiple"); + } } + + void SpeciesThermoFactory:: + installVPThermoForSpecies(int k, const XML_Node& speciesNode, + VPStandardStateTP *vp_ptr, + VPSSMgr *vpssmgr_ptr, + SpeciesThermo *spthermo_ptr, + const XML_Node *phaseNode_ptr) { + + vp_ptr->createInstallPDSS(k, speciesNode, phaseNode_ptr); + } + + + } diff --git a/Cantera/src/thermo/SpeciesThermoFactory.h b/Cantera/src/thermo/SpeciesThermoFactory.h index b1d12814a..b4657159c 100755 --- a/Cantera/src/thermo/SpeciesThermoFactory.h +++ b/Cantera/src/thermo/SpeciesThermoFactory.h @@ -25,6 +25,8 @@ namespace Cantera { class XML_Node; + class VPStandardStateTP; + class VPSSMgr; /** * Throw a named error for an unknown or missing species thermo model. @@ -52,6 +54,20 @@ namespace Cantera { //! Factory to build instances of classes that manage the //! standard-state thermodynamic properties of a set of species. /*! + * This class is responsible for making the decision concerning + * which derivative of SpeciesThermo object to use. + * The SpeciesThermo object is used to calculate + * thermodynamic functions for the reference state. + * It queries the database of species to understand what + * the requirements are for the submodels for all of the + * species in the phase. Then, it picks the SpeciesThermo + * object to use, and passies it back to the calling routine. + * It doesn't load any of the data into the derived + * SpeciesThermo object. + * + * Making the choice of SpeciesThermo types is the only + * thing this class does. + * * 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 @@ -154,20 +170,46 @@ namespace Cantera { SpeciesThermo* newSpeciesThermoOpt(std::vector spData_nodes); //! Install a species thermodynamic property parameterization - //! for one species into a species thermo manager. + //! for the reference state for one species into a species thermo manager. /*! * @param k species number - * @param s Reference to the XML node specifying the species standard + * @param speciesNode Reference to the XML node specifying the species standard * state information * @param spthermo Species reference state thermo manager * @param phaseNode_ptr Optional Pointer to the XML phase * information for the phase in which the species * resides */ - void installThermoForSpecies(int k, const XML_Node& s, + void installThermoForSpecies(int k, const XML_Node& speciesNode, SpeciesThermo& spthermo, const XML_Node *phaseNode_ptr = 0); + //! Install a species thermodynamic property parameterization + //! for the standard state for one species into a species thermo manager, VPSSMgr + /*! + * This is a wrapper around the createInstallVPSS() function in the + * VPStandardStateTP object. + * + * This serves to install the species into vpss_ptr, create a PDSS file. We also + * read the xml database to extract the constants for these steps. + * + * @param k species number + * @param speciesNode Reference to the XML node specifying the species standard + * state information + * @param vp_ptr variable pressure ThermoPhase object + * @param vpss_ptr Pointer to the Manager for calculating variable pressure + * substances. + * @param spthermo_ptr Species reference state thermo manager + * @param phaseNode_ptr Optional Pointer to the XML phase + * information for the phase in which the species + * resides + */ + void installVPThermoForSpecies(int k, const XML_Node& speciesNode, + VPStandardStateTP *vp_ptr, + VPSSMgr *vpss_ptr, + SpeciesThermo *spthermo_ptr, + const XML_Node *phaseNode_ptr); + private: //! pointer to the sole instance of this class diff --git a/Cantera/src/thermo/State.h b/Cantera/src/thermo/State.h index 4b8e100a8..c7bdda3b5 100755 --- a/Cantera/src/thermo/State.h +++ b/Cantera/src/thermo/State.h @@ -298,11 +298,11 @@ namespace Cantera { doublereal temperature() const { return m_temp; } /// Density (kg/m^3). - doublereal density() const { return m_dens; } + virtual doublereal density() const { return m_dens; } /// Molar density (kmol/m^3). doublereal molarDensity() const { - return m_dens/meanMolecularWeight(); + return density()/meanMolecularWeight(); } //! Set the internally storred density (kg/m^3) of the phase @@ -328,10 +328,8 @@ namespace Cantera { * 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) { + virtual void setTemperature(doublereal temp) { m_temp = temp; } //@} diff --git a/Cantera/src/thermo/ThermoFactory.cpp b/Cantera/src/thermo/ThermoFactory.cpp index d1d2682d9..9e8775d55 100644 --- a/Cantera/src/thermo/ThermoFactory.cpp +++ b/Cantera/src/thermo/ThermoFactory.cpp @@ -24,6 +24,8 @@ #include "speciesThermoTypes.h" #include "SpeciesThermoFactory.h" #include "IdealGasPhase.h" +#include "VPSSMgr.h" +#include "VPSSMgrFactory.h" #ifdef WITH_IDEAL_SOLUTIONS #include "IdealSolidSolnPhase.h" @@ -67,6 +69,8 @@ #include "IdealMolalSoln.h" #endif +#include "IdealSolnGasVPSS.h" + using namespace std; namespace Cantera { @@ -76,19 +80,19 @@ namespace Cantera { boost::mutex ThermoFactory::thermo_mutex; #endif - static int ntypes = 13; + static int ntypes = 14; static string _types[] = {"IdealGas", "Incompressible", "Surface", "Edge", "Metal", "StoichSubstance", "PureFluid", "LatticeSolid", "Lattice", "HMW", "IdealSolidSolution", "DebyeHuckel", - "IdealMolalSolution" + "IdealMolalSolution", "IdealGasVPSS" }; static int _itypes[] = {cIdealGas, cIncompressible, cSurf, cEdge, cMetal, cStoichSubstance, cPureFluid, cLatticeSolid, cLattice, cHMW, cIdealSolidSolnPhase, cDebyeHuckel, - cIdealMolalSoln + cIdealMolalSoln, cVPSS_IdealGas }; /* @@ -172,6 +176,10 @@ namespace Cantera { break; #endif + case cVPSS_IdealGas: + th = new IdealSolnGasVPSS; + break; + default: throw UnknownThermoPhaseModel("ThermoFactory::newThermoPhase", model); @@ -256,10 +264,6 @@ namespace Cantera { 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. @@ -274,10 +278,9 @@ namespace Cantera { "unphysical number of dimensions: "+phase["dim"]); th->setNDim(idim); } - else + else { th->setNDim(3); // default - - + } // Set equation of state parameters. The parameters are // specific to each subclass of ThermoPhase, so this is done @@ -287,6 +290,21 @@ namespace Cantera { th->setParametersFromXML(eos); } + VPStandardStateTP *vpss_ptr = 0; + int ssConvention = th->standardStateConvention(); + if (ssConvention == cSS_CONVENTION_VPSS) { + vpss_ptr = dynamic_cast (th); + if (vpss_ptr == 0) { + throw CanteraError("importPhase", + "phase was VPSS, but dynamic cast failed"); + } + } + + // if no species thermo factory was supplied, + // use the default one. + if (!spfactory) { + spfactory = SpeciesThermoFactory::factory(); + } /*************************************************************** * Add the elements. @@ -348,16 +366,27 @@ namespace Cantera { // delete it since we are adding new species. delete &th->speciesThermo(); - // create a new species thermo manager. Function + // Decide whether the the phase has a variable pressure ss or not + SpeciesThermo* spth = 0; + VPSSMgr* vp_spth = 0; + if (ssConvention == cSS_CONVENTION_TEMPERATURE) { + // 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); + spth = newSpeciesThermoMgr(dbases); // install it in the phase object - th->setSpeciesThermo(spth); - SpeciesThermo& spthermo = th->speciesThermo(); + th->setSpeciesThermo(spth); + // SpeciesThermo& spthermo = th->speciesThermo(); + } else { + vp_spth = newVPSSMgr(vpss_ptr, &phase, dbases); + vpss_ptr->setVPSSMgr(vp_spth); + spth = vp_spth->SpeciesThermoMgr(); + th->setSpeciesThermo(spth); + } + // used to check that each species is declared only once map declared; @@ -419,8 +448,8 @@ namespace Cantera { // 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], - &phase, spfactory)) + if (installSpecies(k, *s, *th, spth, sprule[jsp], + &phase, vp_spth, spfactory)) ++k; } else { @@ -437,6 +466,7 @@ namespace Cantera { th->saveSpeciesData(db); // Perform any required subclass-specific initialization. + th->initThermo(); string id = ""; th->initThermoXML(phase, id); @@ -484,8 +514,9 @@ namespace Cantera { * Returns true if everything is ok, false otherwise. */ bool installSpecies(int k, const XML_Node& s, thermo_t& p, - SpeciesThermo& spthermo, int rule, + SpeciesThermo *spthermo_ptr, int rule, XML_Node *phaseNode_ptr, + VPSSMgr *vpss_ptr, SpeciesThermoFactory* factory) { std::string xname = s.name(); @@ -540,10 +571,17 @@ namespace Cantera { // 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, phaseNode_ptr); - + if (vpss_ptr) { + VPStandardStateTP *vp_ptr = dynamic_cast(&p); + factory->installVPThermoForSpecies(k, s, vp_ptr, vpss_ptr, spthermo_ptr, + phaseNode_ptr); + } else { + // install the thermo parameterization for this species into + // the species thermo manager for phase p. + factory->installThermoForSpecies(k, s, *spthermo_ptr, phaseNode_ptr); + } + + return true; } diff --git a/Cantera/src/thermo/ThermoFactory.h b/Cantera/src/thermo/ThermoFactory.h index 33751a4b3..badebb692 100644 --- a/Cantera/src/thermo/ThermoFactory.h +++ b/Cantera/src/thermo/ThermoFactory.h @@ -29,6 +29,7 @@ namespace Cantera { class SpeciesThermoFactory; + class VPSSMgr; /*! * @addtogroup thermoprops @@ -269,7 +270,7 @@ namespace Cantera { * @param k Species Index in the phase * @param s XML_Node containing the species data for this species. * @param p Reference to the ThermoPhase object. - * @param spthermo Reference to the SpeciesThermo object, where + * @param spthermo_ptr Reference to the SpeciesThermo object, where * the standard state thermo properties for this * species will be installed. * @param rule Parameter that handles what to do with species @@ -280,6 +281,8 @@ namespace Cantera { * otherwise, throw an exception * @param phaseNode_ptr Pointer to the XML_Node for this phase * (defaults to 0) + * @param vpss_ptr pointer to the Manager that calculates standard + * state thermo properties * @param factory Pointer to the SpeciesThermoFactory . * (defaults to 0) * @@ -287,8 +290,9 @@ namespace Cantera { * Returns true if everything is ok, false otherwise. */ bool installSpecies(int k, const XML_Node& s, thermo_t& p, - SpeciesThermo& spthermo, int rule, - XML_Node *phaseNode_ptr = 0, + SpeciesThermo* spthermo_ptr, int rule, + XML_Node *phaseNode_ptr = 0, + VPSSMgr *vpss_ptr = 0, SpeciesThermoFactory* factory = 0); //!Search an XML tree for species data. diff --git a/Cantera/src/thermo/ThermoPhase.cpp b/Cantera/src/thermo/ThermoPhase.cpp index 91dbd2bef..6301caa0d 100644 --- a/Cantera/src/thermo/ThermoPhase.cpp +++ b/Cantera/src/thermo/ThermoPhase.cpp @@ -41,7 +41,8 @@ namespace Cantera { m_index(-1), m_phi(0.0), m_hasElementPotentials(false), - m_chargeNeutralityNecessary(false) + m_chargeNeutralityNecessary(false), + m_ssConvention(cSS_CONVENTION_TEMPERATURE) { } @@ -62,7 +63,8 @@ namespace Cantera { m_index(-1), m_phi(0.0), m_hasElementPotentials(false), - m_chargeNeutralityNecessary(false) + m_chargeNeutralityNecessary(false), + m_ssConvention(cSS_CONVENTION_TEMPERATURE) { /* * Call the assignment operator @@ -104,7 +106,7 @@ namespace Cantera { m_lambdaRRT = right.m_lambdaRRT; m_hasElementPotentials = right.m_hasElementPotentials; m_chargeNeutralityNecessary = right.m_chargeNeutralityNecessary; - + m_ssConvention = right.m_ssConvention; return *this; } @@ -128,6 +130,14 @@ namespace Cantera { return cAC_CONVENTION_MOLAR; } + int ThermoPhase::standardStateConvention() const { + return m_ssConvention; + } + + doublereal ThermoPhase::logStandardConc(int k) const { + return log(standardConcentration(k)); + } + void ThermoPhase::getActivities(doublereal* a) const { getActivityConcentrations(a); int nsp = nSpecies(); @@ -839,11 +849,7 @@ namespace Cantera { * 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 */ diff --git a/Cantera/src/thermo/ThermoPhase.h b/Cantera/src/thermo/ThermoPhase.h index 9efa7d49c..7679e18cd 100755 --- a/Cantera/src/thermo/ThermoPhase.h +++ b/Cantera/src/thermo/ThermoPhase.h @@ -33,6 +33,18 @@ namespace Cantera { //! Standard state uses the molality convention const int cAC_CONVENTION_MOLALITY = 1; //@} + + /*! + * @name CONSTANTS - Specification of the SS conventention + */ + //@{ + //! Standard state uses the molar convention + const int cSS_CONVENTION_TEMPERATURE = 0; + //! Standard state uses the molality convention + const int cSS_CONVENTION_VPSS = 1; + //@} + + class XML_Node; /** @@ -45,14 +57,13 @@ namespace Cantera { * is a large class that describes the interface within %Cantera to Thermodynamic * functions for a phase. * - * * The calculation of thermodynamic functions within %ThermoPhase is * broken down roughly into two or more steps. First, the standard state * properties * of all of the species are calculated at the current temperature and at * either * the current pressure or at a reference pressure. If the calculation is - * carried out at a refereence pressure instead of at the current pressure + * carried out at a reference pressure instead of at the current pressure * the calculation is called a "reference state properties" calculation, * just to make the distinction (even though it may be considered to be * a fixed-pressure standard-state calculation). The next step is to @@ -77,10 +88,257 @@ namespace Cantera { * and 5 functions multiplied together makes 25 possible functions. That's * why %ThermoPhase is such a large class. * + *

+ * Categorizing the Different %ThermoPhase Objects + *

+ * + * ThermoPhase objects may be catelogged into four general bins. + * + * The first type are those whose underlying species have a reference state associated + * with them. The reference state describes the thermodynamic functions for a + * species at a single reference pressure, \f$p_0\f$. The thermodynamic functions + * are specified via derived objects of the SpeciesThermoInterpType object class, and usually + * consist of polynomials in temperature such as the NASA polynomial or the SHOMATE + * polynomial. Calculators for these + * reference states, which manage the calculation for all of the species + * in a phase, are all derived from the virtual base class SimpleThermo. Calculators + * are needed because the actual calculation of the reference state thermodynamics + * has been shown to be relatively expensive. A great deal of work has gone + * into devising efficient schemes for calculating the thermodynamic polynomials + * of a set of species in a phase, in particular gas species in ideal gas phases + * whose reference state thermodynamics is specified by NASA polynomials. + * + * The reference state thermodynamics combined with the mixing rules and + * an assumption about the pressure dependence yields the thermodynamic functions for + * the phase. + * Expressions involving the specification of the fugacities of species would fall into + * this category of %ThermoPhase objects. Note, however, that at this time, we do not + * have any nontrivial examples of these types of phases. + * In general, the independent variables that completely describe the state of the + * system for this class are temperature, the + * phase density, and \f$ N - 1 \f$ species mole or mass fractions. + * Additionally, if the + * phase involves charged species, the phase electric potential is an added independent variable. + * Examples of the first class of %ThermoPhase functions, which includes the + * IdealGasPhase object, the most commonly used object with %Cantera, are given below. + * + * - IdealGasPhase in IdealGasPhase.h + * - StoichSubstance in StoichSubstance.h + * - SurfPhase in SurfPhase.h + * - EdgePhase in EdgePhase.h + * - LatticePhase in LatticePhase.h + * - LatticeSolidPhase in LatticeSolidPhase.h + * - ConstDensityThermo in ConstDensityThermo.h + * - PureFluidPhase in PureFluidPhase.h + * - IdealSolidSolnPhase in IdealSolidSolnPhase.h + * - VPStandardStateTP in VPStandardStateTP.h + * + * The second class of objects are actually all derivatives of the VPStandardState + * class listed above. These classes assume that there exists a standard state + * for each species in the phase, where the Thermodynamic functions are specified + * as a function of temperature and pressure. Standard state objects for each + * species are all derived from the PDSS virtual base class. Calculators for these + * standard state, which coordinate the calculation for all of the species + * in a phase, are all derived from the virtual base class VPSSMgr. + * In turn, these standard states may employ reference state calculation to + * aid in their calculations. And the VPSSMgr calculators may also employ + * SimpleThermo calculators to help in calculating the properties for all of the + * species in a phase. However, there are some PDSS objects which do not employ + * reference state calculations. An example of this is real equation of state for + * liquid water used within the calculation of brine thermodynamcis. + * In general, the independent variables that completely describe the state of the + * system for this class are temperature, the + * phase pressure, and N - 1 species mole or mass fractions or molalities. + * The standard state thermodynamics combined with the mixing rules yields + * the thermodynamic functions for the phase. Mixing rules are given in terms + * of specifying the molar-base activity coefficients or activities. + * Lists of phases which belong to this group are given below + * + * - IdealSolnGasVPSS in IdealSolnGasVPSS.h + * - MolalityVPSSTP in MolalityVPSSTP.h + * + * Note, the ideal gas and ideal solution approximations are lumped together + * in the class IdealSolnGasVPSS, because at this level they look alike having + * the same mixing rules with respect to the specification of the excess + * thermodynamic properties. + * The third class of objects are actually all derivatives of the MolalityVPSSTP + * object. They assume that the standard states are temperature and + * pressure dependent. But, they also assume that the standard states are + * molality-based. In other words they assume that the standard state of the solute + * species are in a pseudo state of 1 molality but at infinite dilution. + * A solvent must be specified in these calculations. The solvent is assumed + * to be species zero, and its standard state is the pure solvent state. + * Lists of phases which belong to this group are: + * + * - DebyeHuckel in DebyeHuckel.h + * - IdealMolalSoln in IdealMolalSoln.h + * - HMWSoln in HMWSoln.h + * + * The fourth class of %ThermoPhase objects are stoichiometric phases. + * Stoichiometric phases are phases which consist of one and only one + * species. The class SingleSpeciesTP is the base class for these + * substances. Within the class, the general %ThermoPhase interface is + * dumbed down so that phases consisting of one species may be + * succinctly described. + * These phases may have PDSS classes or SimpleThermo calculators associated + * with them. + * In general, the independent variables that completely describe the state of the + * system for this class are temperature and either the + * phase density or the phase pressure. + * Lists of classes in this group are given below. + * + * - StoichSubstanceSSTP in StoichSubstanceSSTP.h + * - WaterSSTP in WaterSSTP.h + * + * The reader may note that there are duplications in functionality in the + * above lists. This is true. And, it's used for the internal verification of + * capabilities within %Cantera's unit tests. + * + * + *

+ * Setting the %State of the phase + *

+ * + * Typically, the way the ThermoPhase object works is that there are a set + * of functions that set the state of the phase via setting the internal + * independent variables. Then, there are another set of functions that + * query the thermodynamic functions evalulated at the current %State of the + * phase. Internally, most of the intermediate work generally occurs at the + * point where the internal state of the system is set and not at the time + * when individual thermodynamic functions are queried (though the actual + * breakdown in work is dependent on the individual derived ThermoPhase object). + * Therefore, for efficiency, the user should lump together queries of thermodynamic functions + * after setting the state. Moreover, in setting the state, if the + * density is the independent variable, the following order should be + * used: + * + * - Set the temperature + * - Set the mole or mass fractions or set the molalities + * - set the pressure. + * + * For classes which inherit from VPStandardStateTP, the above order may + * be used, or the following order may be used. It's not important. + * + * - Set the temperature + * - Set the pressure + * - Set the mole or mass fractions or set the molalities + * + * The following functions are used to set the state: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
\link ThermoPhase::setState_TPX() setState_TPX()\endlink Sets the temperature, mole fractions and then the pressure + * of the phase.
\link ThermoPhase::setState_TPY() setState_TPY()\endlink Set the temperature, mass fractions and then the pressure + * of the phase.
\link MolalityVPSSTP::setState_TPM() setState_TPM()\endlink Set the temperature, solute molalities, and then the + * pressure of the phase. Only from %ThermoPhase objects which + * inherit from MolalityVPSSTP + *
\link ThermoPhase::setState_TP() setState_TP()\endlink Set the temperature, and then the pressure + * of the phase. The mole fractions are assumed fixed. + *
\link ThermoPhase::setState_PX() setState_PX()\endlink Set the mole fractions and then the pressure + * of the phase. The temperature is assumed fixed. + *
\link ThermoPhase::setState_PY() setState_PY()\endlink Set the mass fractions and then the pressure + * of the phase. The temperature is assumed fixed. + *
\link ThermoPhase::setState_HP() setState_HP()\endlink Set the total specific enthalpy and the pressure + * of the phase using an iterative process. + * The mole fractions are assumed fixed + *
\link ThermoPhase::setState_UV() setState_UV()\endlink Set the total specific internal energy and the pressure + * of the phase using an iterative process. + * The mole fractions are assumed fixed. + *
\link ThermoPhase::setState_SP() setState_SP()\endlink Set the total specific internal energy and the pressure + * of the phase using an iterative process. + * The mole fractions are assumed fixed. + *
\link ThermoPhase::setState_SV() setState_SV()\endlink Set the total specific entropy and the total specific + * molar volume of the phase using an iterative process. + * The mole fractions are assumed fixed. + *
\link State::setConcentrations() setConcentrations()\endlink Set the concentrations of all the species in the + * phase. Note this implicitly specifies the pressure and + * density of the phase. The temperature is assumed fixed. + *
\link State::setDensity() setDensity()\endlink Set the total density of the phase. The temperature and + * mole fractions are assumed fixed. Note this implicity + * sets the pressure of the phase. + *
\link State::setTemperature() setTemperature()\endlink Set the temperature of the phase. The density and + * the mole fractions of the phase are fixed. + *
\link ThermoPhase::setToEquilState() setToEquilState()\endlink Sets the mole fractions of the phase to their + * equilibrium values assuming fixed temperature and + * total density. + *
+ * + * + * + * Some of the functions, like setState_TPX() have multiple forms depending upon + * the format for how the species compositions are set. + * + * + * Molar Basis vs. Molality Basis + * *

* Mechanical properties *

* + * The %ThermoPhase object specifies the mechanical equation of state of the + * phase. Functions which are defined at the %ThermoPhase level to give the + * user more information about the mechanical properties are: + * + * - ThermoPhase::pressure() + * - ThermoPhase::isothermalCompressibility() + * - ThermoPhase::thermalExpansionCoeff() + * . + * *

* Treatment of the %Phase Potential and the electrochemical potential of a species *

@@ -135,42 +393,244 @@ namespace Cantera { * chemical potential to create an effective chemical potential, * may be added at a later time. * - *

- * Setting the %State of the phase - *

+ *

+ * Specification of Activities and Activity Conventions + *

+ * * - * Instantiation of %ThermoPhase properties occurs via the following path. + * The activity \f$a_k\f$ and activity coefficient \f$ \gamma_k \f$ of a + * species in solution is related to the chemical potential by * - * Molar Basis vs. Molality Basis + * \f[ + * \mu_k = \mu_k^0(T,P) + \hat R T \log a_k.= \mu_k^0(T,P) + \hat R T \log x_k \gamma_k + * \f] * - * The following Objects inherit from %ThermoPhase. These are known to the - * internal factory methods + * The quantity \f$\mu_k^0(T,P)\f$ is + * the standard chemical potential at unit activity, + * which depends on the temperature and pressure, + * but not on the composition. The + * activity is dimensionless. Within liquid electrolytes its common to use a + * molality convention, where solute species employ the molality-based + * activity coefficients: * - * - IdealGasPhase in IdealGasPhase.h - * - StoichSubstance in StoichSubstance.h - * - SurfPhase in SurfPhase.h - * - EdgePhase in EdgePhase.h - * - LatticePhase in LatticePhase.h - * - LatticeSolidPhase in LatticeSolidPhase.h - * - ConstDensityThermo in ConstDensityThermo.h - * - PureFluidPhase in PureFluidPhase.h - * . + * \f[ + * \mu_k = \mu_k^\triangle(T,P) + R T ln(a_k^{\triangle}) = + * \mu_k^\triangle(T,P) + R T ln(\gamma_k^{\triangle} \frac{m_k}{m^\triangle}) + * \f] * - * The following additional objects inherit from %ThermoPhase. Most of these - * are associated with an electrochemistry capability that is under - * construction. + * And, the solvent employs the following convention + * \f[ + * \mu_o = \mu^o_o(T,P) + RT ln(a_o) + * \f] * - * - DebyeHuckel in thermo/DebyeHuckel.h - * - SingleSpeciesTP in thermo/SingleSpeciesTP.h - * - StoichSubstanceSSTP in thermo/StoichSubstanceSSTP.h - * - VPStandardStateTP in thermo/VPStandardStateTP.h - * - IdealMolalSoln in thermo/IdealMolalSoln.h - * - IdealSolidSolnPhase in thermo/IdealSolidSolnPhase.h - * - IdealGasPDSS in thermo/IdealGasPDSS.h - * - MolalityVPSSTP in thermo/MolalityVPSSTP.h - * - HMWSoln in thermo/HMWSoln.h - * - WaterSSTP in thermo/WaterSSTP.h - * . + * where \f$ a_o \f$ is often redefined in terms of the osmotic coefficient \f$ \phi \f$. + * + * \f[ + * \phi = \frac{- ln(a_o)}{\tilde{M}_o \sum_{i \ne o} m_i} + * \f] + * + * %ThermoPhase classes which employ the molality based convention are all derived + * from the MolalityVPSSTP class. See the class description for further information + * on its capabilities. + * + * The activity convention used by a %ThermoPhase object + * may be queried via the ThermoPhase::activityConvention() function. A zero means molar based, + * while a one means molality based. + * + * The function ThermoPhase::getActivities() returns a vector of activities. Whether these are + * molar-based or molality-based depends on the value of activityConvention(). + * + * The function getActivityCoefficients() always returns molar-based activity + * coefficients regardless of the activity convention used. The function + * MolalityVPSSTP::getMolalityActivityCoefficients() returns molality + * based activity coefficients for those ThermoPhase objects derived + * from the MolalityVPSSTP class. The function MolalityVPSSTP::osmoticCoefficient() + * returns the osmotic coefficient. + * + *

+ * Activity Concentrations: Relationship of %ThermoPhase to %Kinetics Expressions + *

+ * + * %Cantera can handle both thermodynamics and kinetics mechanisms. Reversible + * kinetics + * mechanisms within %Cantera must be compatible with thermodynamics in the + * sense that at equilibrium, or at infinite times, the concentrations + * of species must conform to thermodynamics. This means that for every + * valid reversible kinetics reaction in a mechanism, it must be reducible to + * an expression involving the ratio of the product activity to + * the reactant activities being equal to the exponential of the + * dimensionless standard state gibbs free energies of reaction. + * Irreversible kinetics reactions do not have this requirement; however, + * their usage can yield unexpected and inconsistent results in many + * situations. + * The actual units used in a kinetics expression depend + * on the context or the relative field of study. For example, in + * gas phase kinetics, species in kinetics expressions are expressed in + * terms of concentrations, i.e., gmol cm-3. In solid phase studies, + * however, kinetics is usually expressed in terms of unitless activities, + * which most often equate to solid phase mole fractions. In order to + * accomodate variability here, %Cantera has come up with the idea + * of activity concentrations, \f$ C^a_k \f$. Activity concentrations are the expressions + * used directly in kinetics expressions. + * 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, + * The activity concentrations for species k, \f$ C^a_k \f$, are + * related to the activity for species, k, \f$ a_k \f$, + * via the following expression: + * + * \f[ + * a_k = C^a_k / C^0_k + * \f] + * + * \f$ C^0_k \f$ are called standard concentrations. They serve as multiplicative factors + * bewteen the activities and the generalized concentrations. Standard concentrations + * may be different for each species. They may depend on both the temperature + * and the pressure. However, they may not depend + * on the composition of the phase. For example, for the IdealGasPhase object + * the standard concentration is defined as + * + * \f[ + * C^0_k = P/ R T + * \f] + * + * In many solid phase kinetics problems, + * + * \f[ + * C^0_k = 1.0 , + * \f] + * + * is employed making the units for activity concentrations in solids unitless. + * + * %ThermoPhase member functions dealing with this concept include + * ThermoPhase::getActivityConcentrations() , which provides a vector of the current + * activity concentrations. The function, ThermoPhase::standardConcentration(int k=0) returns + * the standard concentration of the kth species. The function, + * ThermoPhase::logStandardConc(int k=0), returns the natural log of the kth standard + * concentration. The function ThermoPhase::getUnitsStandardConc() returns a vector of + * doubles, specifying the MKS units of the standard concentration of the + * kth species. + * + * + *

+ * Initialization of %ThermoPhase Objects within %Cantera + *

+ * + * Instantiation of %ThermoPhase properties occurs by reading and + * processing the XML data contained within an ctxml data file. + * First a call to newPhase(std::string file, std::string id) or + * newPhase(XML_Node &phase) + * is made. The arguments serve to specify the + * XML data structure containing the phase information. + * + * Within newPhase() a determination of what type of %ThermoPhase object should be + * used is made. This is done within the routine ThermoFactory::newThermoPhase(std::string model) + * or related routines. + * Once the correct %ThermoPhase derived object is selected and instantiated with a + * bare constructor, the + * function Cantera::importPhase() is called with the %ThermoPhase derived object as + * one of its arguments. + * + * Within importPhase(), a decision is made as to what type of + * standard state, i.e., + * either a reference state (just T dependent) or a standard state + * (both P and T dependent), is to be used to calculate the + * standard state properties of the species within the phase. + * If only a reference state is needed + * then a call to + * \link #newSpeciesThermoMgr(std::vector spData_nodes, SpeciesThermoFactory* f=0, bool opt=false) newSpeciesThermoMgr()\endlink + * is made in order + * pick a manager, i.e., a derivative of the SpeciesThermo + * object, to use. + * + * If a temperature and pressure dependent standard state is needed + * then a call to VPSSMgrFactory::newVPSSMgr() + * is made in order + * pick a manager, i.e., a derivative of the VPSSMgr + * object, to use. Along with the VPSSMgr designation comes a + * determination of whether there is an accompanying SpeciesThermo + * and what type of SpeciesThermo object to use in the + * VPSSMgr calculations. + * + * Once these determinations are made, the %ThermoPhase object is + * ready to start reading in the species information, which includes + * all of the available standard state information about the + * species. this is done within the routine installSpecies(). + * + * Within installSpecies(), most of the common steps for adding a + * species are carried out. The element stoichiometry is read + * and elements are added as needed to the list of elements + * kept with the ThermoPhase object. The charge of the species + * is read in. The species is added into the list + * of species kept within the ThermoPhase object. Lastly, the + * standard state thermodynamics for the species is read in. + * For reference states, the routine, SpeciesThermoFactory::installThermoForSpecies(), + * is used to read in the data. Essentially, this routine is a + * factory routine for picking the correct subroutine to + * call to read the XML data from the input file and install the + * correct SpeciesThermoInterpType object into the SpeciesThermo object. + * + * Within installSpecies(), for standard states, the routine, + * SpeciesThermoFactory::installVPThermoForSpecies() is + * called. However, this is just a shell routine for calling + * the VPSSMgr's derived VPSSMgr::createInstallPDSS() routine. + * Within the VPSSMgr::createInstallPDSS() routine of the derived VPSSMgr's + * object, the XML data from the input file is read and the + * calculations for the species standard state is installed. + * Additionally, the derived PDSS object is created and installed + * into the VPStandardStateTP list containing all of the PDSS objects + * for that phase. + * + * Now that all of the species standard states are read in and + * installed into the ThermoPhase object, control once again + * is returned to the importPhase() function. Two derived functions + * are then called. The first one, ThermoPhase::initThermo(), is called. In this + * routine, all internal arrays within the %ThermoPhase object are + * dimensioned according to the number of elements and species. + * Then, the function ThermoPhase::initThermoXML() is called. + * This function is tasked with reading in all of the thermodynamic + * function information specific to the calculation of the + * phase information. This includes all of the information about + * the activity coefficient calculation. + * + * After the ThermoPhase::initThermoXML() is finished, the + * ThermoPhase routine is ready to receive requests for + * thermodynamic property information. + * + * + * There is an alternative way to instantiate %ThermoPhase objects that + * is applicable to a significant proportion of %ThermoPhase classes. + * The phase may be instantiated via a constructor that invokes the + * XML data structure wherein the phase information is to be read directly. + * In this case, the call to newPhase() and the call to + * ThermoFactory::newThermoPhase(std::string model) + * is not made. However, soon after that, the call to importPhase() is + * made and thereafter instantiation follows the initialization course described + * previously in order to avoid as much duplicate code as possible. + * This alternative way to instantiate %ThermoPhase objects has the + * advantage of working well with hard-coded situations. And, it + * works well also with situations where new %ThermoPhase classes + * are being developed and haven't yet made their way into the + * factory routines. + * + *

+ * Adding Additional Thermodynamics Models + *

+ * + * In general, factory routines throw specific errors when encountering + * unknown thermodynamics models in XML files. All of the error classes + * derive from the class, CanteraError. + * The newVPSSMgr() routines throws the UnknownVPSSMgr class error when + * they encounter an unknown string in the XML input file specifying the + * VPSSMgr class to use. + * + * Many of the important member functions in factory routines are + * virtual classes. This means that a user may write their own + * factory classes which inherit from the base %Cantera factory classes + * to provide additional %ThermoPhase classes. + * * * @see newPhase(std::string file, std::string id) Description for how to * read ThermoPhases from XML files. @@ -303,7 +763,8 @@ namespace Cantera { } - //! Minimum temperature for which the thermodynamic data for the species or phase are valid. + //! Minimum temperature for which the thermodynamic data for the species + //! or phase are valid. /*! * If no argument is supplied, the * value returned will be the lowest temperature at which the @@ -498,6 +959,19 @@ namespace Cantera { */ virtual int activityConvention() const; + //! This method returns the convention used in specification + //! of the standard state, of which there are currently two, + //! temperature based, and variable pressure based. + /*! + * Currently, there are two standard state conventions: + * - Temperature-based activities + * cSS_CONVENTION_TEMPERATURE 0 + * - default + * + * - Variable Pressure and Temperature -based activities + * cSS_CONVENTION_VPSS 1 + */ + virtual int standardStateConvention() const; //! This method returns an array of generalized concentrations /*! @@ -533,9 +1007,10 @@ namespace Cantera { * optional parameter indicating the species. * * @param k Optional parameter indicating the species. The default - * is to assume this refers to species 0. + * is to assume this refers to species 0. * @return - * Returns the standard Concentration in units of m3 kmol-1. + * Returns the standard Concentration. The units are by definition + * dependent on the ThermoPhase and kinetics manager representation. */ virtual doublereal standardConcentration(int k=0) const { err("standardConcentration"); @@ -546,10 +1021,7 @@ namespace Cantera { /*! * @param k index of the species (defaults to zero) */ - virtual doublereal logStandardConc(int k=0) const { - err("logStandardConc"); - return -1.0; - } + virtual doublereal logStandardConc(int k=0) const; //! Returns the units of the standard and generalized concentrations. /*! @@ -1542,6 +2014,7 @@ namespace Cantera { /// Vector of element potentials. /// -> length equal to number of elements vector_fp m_lambdaRRT; + //! Boolean indicating whether there is a valid set of saved element potentials for this phase bool m_hasElementPotentials; @@ -1555,6 +2028,9 @@ namespace Cantera { */ bool m_chargeNeutralityNecessary; + //! Contains the standard state convention + int m_ssConvention; + private: //! Error function that gets called for unhandled cases diff --git a/Cantera/src/thermo/VPSSMgr.cpp b/Cantera/src/thermo/VPSSMgr.cpp new file mode 100644 index 000000000..b35d1e5c2 --- /dev/null +++ b/Cantera/src/thermo/VPSSMgr.cpp @@ -0,0 +1,423 @@ +/** + * @file VPSSMgr.cpp + * Definition file for a virtual base class that manages + * the calculation of standard state properties for all of the + * species in a single phase, assuming a variable P and T standard state + * (see \ref thermoprops and + * class \link Cantera::VPSSMgr VPSSMgr\endlink). + */ +/* + * 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 "VPSSMgr.h" +#include "VPStandardStateTP.h" +#include "SpeciesThermoFactory.h" +#include "PDSS.h" + +using namespace std; + +namespace Cantera { + + class SpeciesThermo; + + VPSSMgr::VPSSMgr(VPStandardStateTP *vptp_ptr, SpeciesThermo *spthermo) : + m_kk(0), + m_vptp_ptr(vptp_ptr), + m_spthermo(spthermo), + m_tlast(-1.0), + m_plast(-1.0), + m_p0(-1.0), + m_minTemp(-1.0), + m_maxTemp(-1.0), + m_useTmpRefStateStorage(false), + m_useTmpStandardStateStorage(false) + { + if (!m_vptp_ptr) { + throw CanteraError("VPSSMgr", + "null pointer for VPStandardStateTP is not permissible"); + } + } + + VPSSMgr::~VPSSMgr() + { + } + + VPSSMgr::VPSSMgr(const VPSSMgr &right) : + m_kk(0), + m_vptp_ptr(0), + m_spthermo(0), + // m_Tnow(300.), + // m_Pnow(OneAtm), + m_tlast(-1.0), + m_plast(-1.0), + m_p0(-1.0), + m_minTemp(-1.0), + m_maxTemp(-1.0), + m_useTmpRefStateStorage(false), + m_useTmpStandardStateStorage(false) + { + *this = right; + } + + VPSSMgr& + VPSSMgr::operator=(const VPSSMgr &right) { + if (&right == this) { + return *this; + } + m_kk = right.m_kk; + m_vptp_ptr = right.m_vptp_ptr; + m_spthermo = right.m_spthermo; + // m_Tnow = right.m_Tnow; + // m_Pnow = right.m_Pnow; + m_tlast = -1.0; + m_plast = -1.0; + m_p0 = right.m_p0; + m_minTemp = right.m_minTemp; + m_maxTemp = right.m_maxTemp; + m_useTmpRefStateStorage = right.m_useTmpRefStateStorage; + m_h0_RT = right.m_h0_RT; + m_cp0_R = right.m_cp0_R; + m_g0_RT = right.m_g0_RT; + m_s0_R = right.m_s0_R; + m_V0 = right.m_V0; + m_useTmpStandardStateStorage = right.m_useTmpStandardStateStorage; + m_hss_RT = right.m_hss_RT; + m_cpss_R = right.m_cpss_R; + m_gss_RT = right.m_gss_RT; + m_sss_R = right.m_sss_R; + m_Vss = right.m_Vss; + + mPDSS_h0_RT = right.mPDSS_h0_RT; + mPDSS_cp0_R = right.mPDSS_cp0_R; + mPDSS_g0_RT = right.mPDSS_g0_RT; + mPDSS_s0_R = right.mPDSS_s0_R; + mPDSS_V0 = right.mPDSS_V0; + mPDSS_hss_RT = right.mPDSS_hss_RT; + mPDSS_cpss_R = right.mPDSS_cpss_R; + mPDSS_gss_RT = right.mPDSS_gss_RT; + mPDSS_sss_R = right.mPDSS_sss_R; + mPDSS_Vss = right.mPDSS_Vss; + + return *this; + } + + VPSSMgr *VPSSMgr::duplMyselfAsVPSSMgr() const { + VPSSMgr *vp = new VPSSMgr(*this); + return vp; + } + + + void VPSSMgr::initAllPtrs(VPStandardStateTP *vp_ptr, + SpeciesThermo *sp_ptr) { + m_vptp_ptr = vp_ptr; + m_spthermo = sp_ptr; + } + + /*****************************************************************/ + // Standard States + + void + VPSSMgr::getStandardChemPotentials(doublereal *mu) const{ + if (m_useTmpStandardStateStorage) { + std::copy(m_gss_RT.begin(), m_gss_RT.end(), mu); + doublereal _rt = GasConstant * m_tlast; + scale(mu, mu+m_kk, mu, _rt); + } else { + err("getStandardChemPotentials"); + } + } + + void + VPSSMgr::getGibbs_RT(doublereal *grt) const{ + if (m_useTmpStandardStateStorage) { + std::copy(m_gss_RT.begin(), m_gss_RT.end(), grt); + } else { + err("getGibbs_RT"); + } + } + + void + VPSSMgr::getEnthalpy_RT(doublereal *hrt) const{ + if (m_useTmpStandardStateStorage) { + std::copy(m_hss_RT.begin(), m_hss_RT.end(), hrt); + } else { + err("getEnthalpy_RT"); + } + } + + void + VPSSMgr::getEntropy_R(doublereal *sr) const{ + if (m_useTmpStandardStateStorage) { + std::copy(m_sss_R.begin(), m_sss_R.end(), sr); + } else { + err("getEntropy_RT"); + } + } + + void + VPSSMgr::getIntEnergy_RT(doublereal *urt) const{ + if (m_useTmpStandardStateStorage) { + std::copy(m_hss_RT.begin(), m_hss_RT.end(), urt); + doublereal pRT = m_plast / (GasConstant * m_tlast); + for (int k = 0; k < m_kk; k++) { + urt[k] -= pRT * m_Vss[k]; + } + } else { + err("getEntropy_RT"); + } + } + + void + VPSSMgr::getCp_R(doublereal *cpr) const{ + if (m_useTmpStandardStateStorage) { + std::copy(m_cpss_R.begin(), m_cpss_R.end(), cpr); + } else { + err("getCp_R"); + } + } + + void + VPSSMgr::getStandardVolumes(doublereal *vol) const{ + if (m_useTmpStandardStateStorage) { + std::copy(m_Vss.begin(), m_Vss.end(), vol); + } else { + err("getStandardVolumes"); + } + } + + /*****************************************************************/ + void + VPSSMgr::getEnthalpy_RT_ref(doublereal *hrt) const{ + if (m_useTmpRefStateStorage) { + std::copy(m_h0_RT.begin(), m_h0_RT.end(), hrt); + } else { + err("getEnthalpy_RT_ref"); + } + } + + void + VPSSMgr::getGibbs_RT_ref(doublereal *grt) const{ + if (m_useTmpRefStateStorage) { + std::copy(m_g0_RT.begin(), m_g0_RT.end(), grt); + } else { + err("getGibbs_RT_ref"); + } + } + + void + VPSSMgr::getGibbs_ref(doublereal *g) const{ + if (m_useTmpRefStateStorage) { + std::copy(m_g0_RT.begin(), m_g0_RT.end(), g); + doublereal _rt = GasConstant * m_tlast; + scale(g, g+m_kk, g, _rt); + } else { + err("getGibbs_ref"); + } + } + + void + VPSSMgr::getEntropy_R_ref(doublereal *sr) const{ + if (m_useTmpRefStateStorage) { + std::copy(m_s0_R.begin(), m_s0_R.end(), sr); + } else { + err("getEntropy_R_ref"); + } + } + + void + VPSSMgr::getCp_R_ref(doublereal *cpr) const{ + if (m_useTmpRefStateStorage) { + std::copy(m_cp0_R.begin(), m_cp0_R.end(), cpr); + } else { + err("getCp_R_ref"); + } + } + + void + VPSSMgr::getStandardVolumes_ref(doublereal *vol) const{ + err("getStandardVolumes_ref"); + } + + /*****************************************************************/ + + void VPSSMgr::setState_P(doublereal pres) { + if (m_plast != pres) { + m_plast = pres; + _updateStandardStateThermo(); + } + } + + void VPSSMgr::setState_T(doublereal temp) { + if (m_tlast != temp) { + m_tlast = temp; + _updateRefStateThermo(); + _updateStandardStateThermo(); + } + } + + void VPSSMgr::setState_TP(doublereal temp, doublereal pres) { + if (m_tlast != temp) { + m_tlast = temp; + m_plast = pres; + _updateRefStateThermo(); + _updateStandardStateThermo(); + } else if (m_plast != pres) { + m_plast = pres; + _updateStandardStateThermo(); + } + } + + void VPSSMgr::updateStandardStateThermo() { + } + + void VPSSMgr::updateRefStateThermo() const { + } + + void VPSSMgr::_updateStandardStateThermo() { + err("_updateStandardStateThermo()"); + } + + void VPSSMgr::_updateRefStateThermo() const { + if (m_spthermo) { + m_spthermo->update(m_tlast, &m_cp0_R[0], &m_h0_RT[0], &m_s0_R[0]); + for (int k = 0; k < m_kk; k++) { + m_g0_RT[k] = m_h0_RT[k] - m_s0_R[k]; + } + } + } + + + /*****************************************************************/ + + void + VPSSMgr::initThermo() { + initLengths(); + } + + void + VPSSMgr::initLengths() { + m_kk = m_vptp_ptr->nSpecies(); + m_h0_RT.resize(m_kk, 0.0); + m_cp0_R.resize(m_kk, 0.0); + m_g0_RT.resize(m_kk, 0.0); + m_s0_R.resize(m_kk, 0.0); + m_V0.resize(m_kk, 0.0); + m_hss_RT.resize(m_kk, 0.0); + m_cpss_R.resize(m_kk, 0.0); + m_gss_RT.resize(m_kk, 0.0); + m_sss_R.resize(m_kk, 0.0); + m_Vss.resize(m_kk, 0.0); + + // Storage used by the PDSS objects to store their + // answers. + mPDSS_h0_RT.resize(m_kk, 0.0); + mPDSS_cp0_R.resize(m_kk, 0.0); + mPDSS_g0_RT.resize(m_kk, 0.0); + mPDSS_s0_R.resize(m_kk, 0.0); + mPDSS_V0.resize(m_kk, 0.0); + mPDSS_hss_RT.resize(m_kk, 0.0); + mPDSS_cpss_R.resize(m_kk, 0.0); + mPDSS_gss_RT.resize(m_kk, 0.0); + mPDSS_sss_R.resize(m_kk, 0.0); + mPDSS_Vss.resize(m_kk, 0.0); + } + + void VPSSMgr::initThermoXML(XML_Node& phaseNode, std::string id) { + // Add a check to see that all references pressures are the same +#ifdef DEBUG_MODE + double m_p0_k; + if (m_spthermo) { + for (int k = 0; k < m_kk; k++) { + m_p0_k = m_spthermo->refPressure(k); + if (m_p0 != m_p0_k) { + //throw CanteraError("VPSSMgr::initThermoXML", + // "inconsistent ref pressures" + fp2str(m_p0) + " " + // + fp2str(m_p0_k)); + // writelog("VPSSMgr::initThermoXML:" + // "inconsistent ref pressures: " + fp2str(m_p0) + " " + // + fp2str(m_p0_k) + " for SpeciesThermo k = " + int2str(k) + "\n"); + } + } + } + + + for (int k = 0; k < m_kk; k++) { + const PDSS *kPDSS = m_vptp_ptr->providePDSS(k); + m_p0_k = kPDSS->refPressure(); + if (m_p0 != m_p0_k) { + //throw CanteraError("VPSSMgr::initThermoXML", + // "inconsistent ref pressures" + fp2str(m_p0) + " " + // + fp2str(m_p0_k)); + //writelog("VPSSMgr::initThermoXML" + // "inconsistent ref pressures: " + fp2str(m_p0) + " " + // + fp2str(m_p0_k) + " for PDSS k = " + int2str(k) + "\n"); + } + } +#endif + } + + void VPSSMgr::installSTSpecies(int k, const XML_Node& s, + const XML_Node *phaseNode_ptr) { + + SpeciesThermoFactory* f = SpeciesThermoFactory::factory(); + f->installThermoForSpecies(k, s, *m_spthermo, phaseNode_ptr); + if (m_p0 < 0.0) { + m_p0 = m_spthermo->refPressure(k); + } + } + + PDSS * VPSSMgr::createInstallPDSS(int k, const XML_Node& s, + const XML_Node *phaseNode_ptr) { + // VPSSMgr_enumType tt = reportVPSSMgrType(); + //string ttt = "createInstallPDSS: " + int2str(int(tt)); + err( "createInstallPDSS: "); + return (PDSS *) 0; + } + + + /*****************************************************************/ + doublereal VPSSMgr::minTemp(int k) const { + return m_minTemp; + } + + doublereal VPSSMgr::maxTemp(int k) const { + return m_maxTemp; + } + + doublereal VPSSMgr::refPressure() const { + return m_p0; + } + + PDSS_enumType VPSSMgr::reportPDSSType(int index) const { + err("reportPDSSType()"); + return cPDSS_UNDEF; + } + + + VPSSMgr_enumType VPSSMgr::reportVPSSMgrType() const { + err("reportVPSSType()"); + return cVPSSMGR_UNDEF; + } + + /*****************************************************************/ + + void VPSSMgr::err(std::string msg) const { + throw CanteraError("VPSSMgr::" + msg, "unimplemented"); + } +} + + diff --git a/Cantera/src/thermo/VPSSMgr.h b/Cantera/src/thermo/VPSSMgr.h new file mode 100644 index 000000000..1f6881b5f --- /dev/null +++ b/Cantera/src/thermo/VPSSMgr.h @@ -0,0 +1,914 @@ +/** + * @file VPSSMgr.h + * Declaration file for a virtual base class that manages + * the calculation of standard state properties for all of the + * species in a single phase, assuming a variable P and T standard state + * (see \ref thermoprops and + * class \link Cantera::VPSSMgr VPSSMgr\endlink). + */ + +/* + * $Author$ + * $Revision$ + * $Date$ + */ +/* + * 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. + */ + +#ifndef CT_VPSSMGR_H +#define CT_VPSSMGR_H + +#include "ct_defs.h" +#include "mix_defs.h" + +namespace Cantera { + + class SpeciesThermoInterpType; + class VPStandardStateTP; + class XML_Node; + class SpeciesThermo; + class PDSS; + /** + * @defgroup vpssmgrthermo 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 (almost always at + * 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 in the limit of infinite dilution within 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 particular 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. + * + * Class VPSSMgr is the base class + * for a family of classes that compute properties of all + * species in a phase in their standard states, for a range of temperatures + * and pressures. + * + * Phases which use the VPSSMGr class must have their respective + * ThermoPhase objects actually be derivatives of the VPStandardState + * class. These classes assume that there exists a standard state + * for each species in the phase, where the Thermodynamic functions are specified + * as a function of temperature and pressure. Standard state objects for each + * species in the phase are all derived from the PDSS virtual base class. + * Calculators for these + * standard state, which coordinate the calculation for all of the species + * in a phase, are all derived from VPSSMgr. + * In turn, these standard states may employ reference state calculation to + * aid in their calculations. And the VPSSMgr calculators may also employ + * SimpleThermo calculators to help in calculating the properties for all of the + * species in a phase. However, there are some PDSS objects which do not employ + * reference state calculations. An example of this is real equation of state for + * liquid water used within the calculation of brine thermodynamcis. + * In general, the independent variables that completely describe the state of the + * system for this class are temperature, the + * phase pressure, and N - 1 species mole or mass fractions or molalities. + * The standard state thermodynamics combined with the mixing rules yields + * the thermodynamic functions for the phase. Mixing rules are given in terms + * of specifying the molar-base activity coefficients or activities. + * Lists of phases which belong to this group are given below + * + * + * The following classes inherit from VPSSMgr. Each of these classes + * handle multiple species and by definition all of the species in a phase. + * It is a requirement that a VPSSMgr object handles all of the + * species in a phase. + + * + * - VPSSMgr_IdealGas + * - standardState model = "IdealGas" + * - This model assumes that all species in the phase obey the + * ideal gas law for their pressure dependence. The manager + * uses a SimpleThermo object to handle the calculation of the + * reference state. + * . + * + * - VPSSMgr_ConstVol + * - standardState model = "ConstVol" + * - This model assumes that all species in the phase obey the + * constant partial molar volume pressure dependence. + * The manager uses a SimpleThermo object to handle the + * calculation of the reference state. + * . + * + * - VPSSMgr_Water_ConstVol + * - standardState model = "Water_ConstVol" + * - This model assumes that all species but one in the phase obey the + * constant partial molar volume pressure dependence. + * The manager uses a SimpleThermo object to handle the + * calculation of the reference state for those species. + * Species 0 is assumed to be water, and a real equation + * of state is used to model the T, P behavior. + * . + * + * - VPSSMgr_Water_HKFT. + * - standardState model = "Water_HKFT" + * - This model assumes that all species but one in the phase obey the + * HKFT equation of state. + * Species 0 is assumed to be water, and a real equation + * of state is used to model the T, P behavior. + * . + * + * - VPSSMgr_General + * - standardState model = "General" + * - This model is completely general. Nothing is assumed at this + * level. Calls consist of loops to PDSS property evalulations. + * . + * + * The choice of which VPSSMGr object to be used is implicitly made by + * Cantera by querying the XML data file for compatibility. + * However, each of these VPSSMgr objects may be explicitly requested in the XML file + * by adding in the following XML nodes into the thermo section of the + * phase XML Node. For example, this explicitly requests that the VPSSMgr_IdealGas + * object be used to handle the standard state calculations. + * + * @verbatim + + + <\thermo> + @endverbatim + * + * + * @ingroup phases + */ + + //! Virtual base class for the classes that manage the calculation + //! of standard state properties for all the species in a phase. + /*! + * This class defines the interface which all subclasses must implement. + * + * Class %VPSSMgr is the base class + * for a family of classes that compute properties of a set of + * species in their standard state at a range of temperatures + * and pressures. + * + * and pressure are unchanged. + * + * If #m_useTmpRefStateStorage is set to true, then the following internal + * arrays, containing information about the reference arrays, + * are calculated and kept up to date at every call. + * + * - #m_h0_RT + * - #m_g0_RT + * - #m_s0_R + * - #m_cp0_R + * + * The virtual function #_updateRefStateThermo() is supplied to do this + * and may be reimplemented in child routines. A default implementation + * based on the speciesThermo class is supplied in this base class. + * #_updateStandardStateThermo() is called whenever a reference state + * property is needed. + * + * When #m_useTmpStandardStateStorage is true, then the following + * internal arrays, containing information on the standard state properties + * are calculated and kept up to date. + * + * - #m_hss_RT; + * - #m_cpss_R; + * - #m_gss_RT; + * - #m_sss_R; + * - #m_Vss + * + * The virtual function #_updateStandardStateThermo() is supplied to do this + * and must be reimplemented in child routines, + * when #m_useTmpStandardStateStorage is true. + * It may be optionally reimplemented in child routines if + * #m_useTmpStandardStateStorage is false. + * #_updateStandardStateThermo() is called whenever a standard state property is needed. + * + * This class is usually used for nearly incompressible phases. For those phases, it + * makes sense to change the equation of state independent variable from + * density to pressure. + * + */ + class VPSSMgr { + + public: + + //! Constructor + /*! + * @param vptp_ptr Pointer to the Variable pressure %ThermoPhase object + * This object must have already been malloced. + * + * @param spth Pointer to the optional SpeciesThermo object + * that will handle the calculation of the reference + * state thermodynamic coefficients. + */ + VPSSMgr(VPStandardStateTP *vptp_ptr, SpeciesThermo *spth = 0); + + //! Destructor + virtual ~VPSSMgr(); + + //! Copy Constructor for the %SpeciesThermo object. + /*! + * @param right Reference to %SpeciesThermo object to be copied into the + * current one. + */ + VPSSMgr(const VPSSMgr &right); + + //! Assignment operator for the %SpeciesThermo object + /*! + * This is NOT a virtual function. + * + * @param right Reference to %SpeciesThermo object to be copied into the + * current one. + */ + VPSSMgr& operator=(const VPSSMgr &right); + + //! Duplication routine for objects which inherit from + //! %VPSSMgr + /*! + * This virtual routine can be used to duplicate %VPSSMgr objects + * inherited from %VPSSMgr even if the application only has + * a pointer to %VPSSMgr to work with. + */ + virtual VPSSMgr *duplMyselfAsVPSSMgr() const; + + + /*! + * @name Properties of the Standard State of the Species in the Solution + * + */ + //@{ + + //!Get the array of chemical potentials at unit activity. + /*! + * These are the standard state chemical potentials \f$ \mu^0_k(T,P) + * \f$. The values are evaluated at the current temperature and pressure. + * + * @param mu Output vector of standard state chemical potentials. + * length = m_kk. units are J / kmol. + */ + virtual void getStandardChemPotentials(doublereal* mu) const; + + /** + * Get the nondimensional Gibbs functions for the species + * at their standard states of solution at the current T and P + * 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 nondimensional Enthalpy functions for the species + * at their standard states at the current + * T and P of the solution. + * + * @param hrt Output vector of standard state enthalpies. + * length = m_kk. units are unitless. + */ + virtual void getEnthalpy_RT(doublereal* hrt) const; + + //! Return a reference to a vector of the molar enthalpies of the + //! species in their standard states + const vector_fp& enthalpy_RT() const { + return m_hss_RT; + } + + /** + * Get the array of nondimensional Enthalpy functions for the + * standard state species + * at the current T and P of the solution. + * + * @param sr Output vector of nondimensional standard state + * entropies. length = m_kk. + */ + virtual void getEntropy_R(doublereal* sr) const; + + //! Return a reference to a vector of the entropies of the + //! species + const vector_fp& entropy_R() const { + return m_sss_R; + } + + //! Returns the vector of nondimensional + //! internal Energies of the standard state at the current temperature + //! and pressure of the solution for each species. + /*! + * The internal energy is calculated from the enthalpy from the + * following formula: + * + * \f[ + * u^{ss}_k(T,P) = h^{ss}_k(T) - P * V^{ss}_k + * \f] + * + * @param urt Output vector of nondimensional standard state + * internal energies. length = m_kk. + */ + virtual void getIntEnergy_RT(doublereal *urt) const; + + //! Get the nondimensional Heat Capacities at constant + //! pressure for the standard state of the species + //! at the current T and P. + /*! + * + * This is redefined here to call the internal function, _updateStandardStateThermo(), + * which calculates all standard state properties at the same time. + * + * @param cpr Output vector containing the + * the nondimensional Heat Capacities at constant + * pressure for the standard state of the species. + * Length: m_kk. + */ + virtual void getCp_R(doublereal* cpr) const; + + //! Return a reference to a vector of the constant pressure + //! heat capacities of the species + const vector_fp& cp_R() const { + return m_cpss_R; + } + + //! Get the molar volumes of each species in their standard + //! states at the current + //! T and P of the solution. + /*! + * units = m^3 / kmol + * + * This is redefined here to call the internal function, + * _updateStandardStateThermo(), + * which calculates all standard state properties at the same time. + * + * @param vol Output vector of species volumes. length = m_kk. + * units = m^3 / kmol + */ + virtual void getStandardVolumes(doublereal *vol) const; + + //! Return a reference to a vector of the species standard molar volumes + const vector_fp& standardVolumes() const { + return m_Vss; + } + + public: + + //@} + /// @name Thermodynamic Values for the Species Reference States (VPStandardStateTP) + /*! + * There are also temporary + * variables for holding the species reference-state values of Cp, H, S, and V at the + * last temperature and reference pressure called. These functions + * are not recalculated + * if a new call is made using the previous temperature. + * All calculations are done within the routine _updateRefStateThermo(). + */ + //@{ + + /*! + * 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 contains the nondimensional enthalpies + * of the reference state of the species + * length = m_kk, units = dimensionless. + */ + 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 contains the nondimensional Gibbs free energies + * of the reference state of the species + * length = m_kk, units = dimensionless. + */ + virtual void getGibbs_RT_ref(doublereal *grt) const ; + + + //! Return a reference to the vector of Gibbs free energies of the species + const vector_fp & Gibbs_RT_ref() const { + return m_g0_RT; + } + + /*! + * 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 contain the Gibbs free energies + * of the reference state of the species + * 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 the species. + * + * @param er Output vector contain the nondimensional entropies + * of the species in their reference states + * length: m_kk, units: dimensionless. + */ + virtual void getEntropy_R_ref(doublereal *er) 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 the species. + * + * @param cpr Output vector contains the nondimensional heat capacities + * of the species in their reference states + * length: m_kk, units: dimensionless. + */ + virtual void getCp_R_ref(doublereal *cpr) const ; + + //! Get the molar volumes of the species reference states at the current + //! T and P_ref 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 Setting the Internal State of the System + /*! + * All calls to change the internal state of the system's T and P + * are done through these routines + * - setState_TP() + * - setState_T() + * - setState_P() + * + * These routine in turn call the following underlying virtual functions + * + * - _updateRefStateThermo() + * - _updateStandardStateThermo() + * + * An important point to note is that inbetween calls the assumption + * that the underlying PDSS objects will retain their set Temperatures + * and Pressure CAN NOT BE MADE. For efficiency reasons, we may twiddle + * these to get derivatives. + */ + //@{ + + //! Set the temperature (K) and pressure (Pa) + /*! + * This sets the temperature and pressure and triggers + * calculation of underlying quantities + * + * @param T Temperature (K) + * @param P Pressure (Pa) + */ + virtual void setState_TP(doublereal T, doublereal P); + + //! Set the temperature (K) + /*! + * @param T Temperature (K) + */ + virtual void setState_T(doublereal T); + + //! Set the pressure (Pa) + /*! + * @param P Pressure (Pa) + */ + virtual void setState_P(doublereal P); + + //! Return the temperatue storred in the object + doublereal temperature() const { + return m_tlast; + } + + //! Return the pressure storred in the object + doublereal pressure() const { + return m_plast; + } + + //! Return the pointer to the reference-state Thermo calculator + //! SpeciesThermo object. + SpeciesThermo *SpeciesThermoMgr() { + return m_spthermo; + } + + //! Updates the internal standard state thermodynamic vectors at the + //! current T and P of the solution. + /*! + * If you are to peak internally inside the object, you need to + * call these functions after setState functions in order to be sure + * that the vectors are current. + */ + virtual void updateStandardStateThermo(); + + //! Updates the internal reference state thermodynamic vectors at the + //! current T of the solution and the reference pressure. + /*! + * If you are to peak internally inside the object, you need to + * call these functions after setState functions in order to be sure + * that the vectors are current. + */ + virtual void updateRefStateThermo() const; + + protected: + + //! Updates the standard state thermodynamic functions at the + //! current T and P of the solution. + /*! + * @internal + * + * If m_useTmpStandardStateStorage is true, + * this function must be called for every call to functions in this + * class. It checks to see whether the temperature or pressure has changed and + * thus the ss thermodynamics functions for all of the species + * must be recalculated. + * + * This function is responsible for updating the following internal members, + * when m_useTmpStandardStateStorage is true. + * + * - m_hss_RT; + * - m_cpss_R; + * - m_gss_RT; + * - m_sss_R; + * - m_Vss + * + * If m_useTmpStandardStateStorage is not true, this function may be + * required to be called by child classes to update internal member data. + * + * Note, this will throw an error. It must be reimplemented in derived classes. + * + * Underscore updates never check for the state of the system + * They just do the calculation. + */ + virtual void _updateStandardStateThermo(); + + //! Updates the reference state thermodynamic functions at the + //! current T of the solution and the reference pressure + /*! + * Underscore updates never check for the state of the system + * They just do the calculation. + */ + virtual void _updateRefStateThermo () const; + + public: + //@} + //! @name Utility Methods - Reports on various quantities + /*! + * The following methods are used in the process of reporting + * various states and attributes + */ + //@{ + + //! This utility function reports the type of parameterization + //! used for the species with index number index. + /*! + * + * @param index Species index + */ + virtual PDSS_enumType reportPDSSType(int index = -1) const ; + + + //! This utility function reports the type of manager + //! for the calculation of ss properties + /*! + * @return Returns an enum type called VPSSMgr_enumType, which is a list + * of the known VPSSMgr objects + */ + virtual VPSSMgr_enumType reportVPSSMgrType() 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 the standard state + /*! + * + * 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. + * + */ + virtual doublereal refPressure() const ; + + + //@} + //! @name Initialization Methods - For Internal use (VPStandardState) + /*! + * The following methods are used in the process of constructing + * the phase and setting its parameters from a specification in an + * input file. They are not normally used in application programs. + * To see how they are used, see files importCTML.cpp and + * ThermoFactory.cpp. + */ + //@{ + + //! @internal Initialize the object + /*! + * 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 + */ + virtual void initThermo(); + + //! Initialize the lengths within the object + /*! + * Note this function is not virtual + */ + void initLengths(); + + //! Finalize the thermo after all species have been entered + /*! + * This function is the LAST initialization routine to be + * called. It's called after createInstallPDSS() has been + * called for each species in the phase, and after initThermo() + * has been called. + * It's called via an inner-to-outer onion shell like manner. + * + * + * @param phaseNode Reference to the phaseNode XML node. + * @param id ID of the phase. + */ + virtual void initThermoXML(XML_Node& phaseNode, std::string id); + + //! Install specific content for species k in the reference-state + //! thermodynamic SpeciesManager object + /*! + * This occurs before matrices are sized appropriately. + * + * @param k Species index in the phase + * @param speciesNode XML Node corresponding to the species + * @param phaseNode_ptr Pointer to the XML Node corresponding + * to the phase which owns the species + */ + void installSTSpecies(int k, const XML_Node& speciesNode, + const XML_Node *phaseNode_ptr); + + //! Install specific content for species k in the standard-state + //! thermodynamic calculator and also create/return a PDSS object + //! for that species. + /*! + * This occurs before matrices are sized appropriately. + * + * @param k Species index in the phase + * @param speciesNode XML Node corresponding to the species + * @param phaseNode_ptr Pointer to the XML Node corresponding + * to the phase which owns the species + */ + virtual PDSS * createInstallPDSS(int k, const XML_Node& speciesNode, + const XML_Node *phaseNode_ptr); + + + + //! Initialize the internal pointers in this object + /*! + * There are a bunch of internal shallow pointers that point to the owning + * VPStandardStateTP and SpeciesThermo objects. This function reinitializes + * them. + * + * @param vp_ptr Pointer to the VPStandardStateTP standard state + * @param sp_ptr Poitner to the SpeciesThermo standard state + */ + virtual void initAllPtrs(VPStandardStateTP *vp_ptr, SpeciesThermo *sp_ptr); + + protected: + + //! Number of species in the phase + int m_kk; + + //! Variable pressure ThermoPhase object + VPStandardStateTP *m_vptp_ptr; + + //! Pointer to reference state thermo calculator + /*! + * Note, this can have a value of 0 + */ + SpeciesThermo *m_spthermo; + + //! The last temperature at which the standard state thermodynamic + //! properties were calculated at. + mutable doublereal m_tlast; + + //! The last pressure at which the Standard State thermodynamic + //! properties were calculated at. + mutable doublereal m_plast; + + /*! + * Reference pressure (Pa) must be the same for all species + * - defaults to 1 atm. + */ + doublereal m_p0; + + //! minimum temperature for the standard state calculations + doublereal m_minTemp; + + //! maximum temperature for the standard state calculations + doublereal m_maxTemp; + + /*! + * boolean indicating whether temporary reference state storage is used + * -> default is false + */ + bool m_useTmpRefStateStorage; + + /*! + * Vector containing the species reference enthalpies at T = m_tlast + * and P = p_ref. + */ + mutable vector_fp m_h0_RT; + + /** + * Vector containing the species reference constant pressure + * heat capacities at T = m_tlast and P = p_ref. + */ + mutable vector_fp m_cp0_R; + + /** + * Vector containing the species reference Gibbs functions + * at T = m_tlast and P = p_ref. + */ + mutable vector_fp m_g0_RT; + + /** + * Vector containing the species reference entropies + * at T = m_tlast and P = p_ref. + */ + mutable vector_fp m_s0_R; + + //! Vector containing the species referenc molar volumes + mutable vector_fp m_V0; + + /*! + * boolean indicating whether temporary standard state storage is used + * -> default is false + */ + bool m_useTmpStandardStateStorage; + + /** + * Vector containing the species Standard State enthalpies at T = m_tlast + * and P = m_plast. + */ + mutable vector_fp m_hss_RT; + + /** + * Vector containing the species Standard State constant pressure + * heat capacities at T = m_tlast and P = m_plast. + */ + mutable vector_fp m_cpss_R; + + /** + * Vector containing the species Standard State Gibbs functions + * at T = m_tlast and P = m_plast. + */ + mutable vector_fp m_gss_RT; + + /** + * Vector containing the species Standard State entropies + * at T = m_tlast and P = m_plast. + */ + mutable vector_fp m_sss_R; + + /** + * Vector containing the species standard state volumes + * at T = m_tlast and P = m_plast + */ + mutable vector_fp m_Vss; + + + //! species reference enthalpies - used by individual PDSS objects + /*! + * Vector containing the species reference enthalpies at T = m_tlast + * and P = p_ref. + */ + mutable vector_fp mPDSS_h0_RT; + + //! species reference heat capacities - used by individual PDSS objects + /** + * Vector containing the species reference constant pressure + * heat capacities at T = m_tlast and P = p_ref. + */ + mutable vector_fp mPDSS_cp0_R; + + //! species reference gibbs free energies - used by individual PDSS objects + /** + * Vector containing the species reference Gibbs functions + * at T = m_tlast and P = p_ref. + */ + mutable vector_fp mPDSS_g0_RT; + + //! species reference entropies - used by individual PDSS objects + /** + * Vector containing the species reference entropies + * at T = m_tlast and P = p_ref. + */ + mutable vector_fp mPDSS_s0_R; + + + //! species reference state molar Volumes - used by individual PDSS objects + /** + * Vector containing the rf molar volumes + * at T = m_tlast and P = p_ref. + */ + mutable vector_fp mPDSS_V0; + + //! species standard state enthalpies - used by individual PDSS objects + /*! + * Vector containing the species standard state enthalpies at T = m_tlast + * and P = p_ref. + */ + mutable vector_fp mPDSS_hss_RT; + + //! species standard state heat capacities - used by individual PDSS objects + /** + * Vector containing the species standard state constant pressure + * heat capacities at T = m_tlast and P = p_ref. + */ + mutable vector_fp mPDSS_cpss_R; + + //! species standard state gibbs free energies - used by individual PDSS objects + /** + * Vector containing the species standard state Gibbs functions + * at T = m_tlast and P = p_ref. + */ + mutable vector_fp mPDSS_gss_RT; + + //! species standard state entropies - used by individual PDSS objects + /** + * Vector containing the species standard state entropies + * at T = m_tlast and P = p_ref. + */ + mutable vector_fp mPDSS_sss_R; + + //! species standard state molar Volumes - used by individual PDSS objects + /** + * Vector containing the ss molar volumes + * at T = m_tlast and P = p_ref. + */ + mutable vector_fp mPDSS_Vss; + + + friend class PDSS; + private: + + //! Error message to indicate an unimplemented feature + /*! + * @param msg Error message string + */ + void err(std::string msg) const; + + }; + //@} +} + +#endif diff --git a/Cantera/src/thermo/VPSSMgrFactory.cpp b/Cantera/src/thermo/VPSSMgrFactory.cpp new file mode 100644 index 000000000..9ea97c19b --- /dev/null +++ b/Cantera/src/thermo/VPSSMgrFactory.cpp @@ -0,0 +1,349 @@ +/** + * @file VPSSMgrFactory.cpp + * Definitions for factory to build instances of classes that manage the + * calculation of standard state properties for all the species in a phase + * (see \ref spthermo and class + * \link Cantera::VPSSMgrFactory VPSSMgrFactory\endlink); + */ +/* + * $Id$ + */ + +/* + * 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. + */ +#ifdef WIN32 +#pragma warning(disable:4786) +#endif + + +#include "SpeciesThermo.h" + + +#include "VPSSMgr.h" +#include "VPSSMgrFactory.h" + +#include "VPStandardStateTP.h" + +#include "VPSSMgr_IdealGas.h" +#include "VPSSMgr_ConstVol.h" +#include "VPSSMgr_Water_ConstVol.h" +#include "VPSSMgr_Water_HKFT.h" +#include "VPSSMgr_General.h" + +#include "VPSSMgr_types.h" + +#include "SpeciesThermoMgr.h" +#include "speciesThermoTypes.h" +#include "SpeciesThermo.h" +#include "SpeciesThermoFactory.h" +#include "GeneralSpeciesThermo.h" + +#include "mix_defs.h" + +#include "xml.h" +#include "ctml.h" + +using namespace ctml; +using namespace std; + + +namespace Cantera { + + VPSSMgrFactory* VPSSMgrFactory::s_factory = 0; + +#if defined(THREAD_SAFE_CANTERA) + // Defn of the static mutex variable that locks the + // %VPSSMgr factory singelton + boost::mutex VPSSMgrFactory::vpss_species_thermo_mutex; +#endif + + /* + * 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 getVPSSMgrTypes(XML_Node* spData_node, + int& has_nasa, int& has_shomate, int& has_simple, + int &has_water, + int &has_tpx, + int &has_hptx, + int &has_other) { + + const XML_Node& sparray = *spData_node; + std::vector 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("standardState")) { + const XML_Node& ssN = sp[n]->child("standardState"); + string mm = ssN["model"]; + if (mm == "waterIAPWS" || mm == "waterPDSS") { + has_water++; + } + } else { + + 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; + if (th.hasChild("NASA9")) has_other = 1; + if (th.hasChild("NASA9MULTITEMP")) has_other = 1; + if (th.hasChild("adsorbate")) has_other = 1; + } else { + throw UnknownVPSSMgrModel("getVPSSMgrTypes:", + spNode->attrib("name")); + } + } + } + } + + VPSSMgr_enumType + VPSSMgrFactory::VPSSMgr_StringConversion(std::string ssModel) const { + VPSSMgr_enumType type; + if (ssModel == "IdealGas") { + type = cVPSSMGR_IDEALGAS; + } else if (ssModel == "ConstVol") { + type = cVPSSMGR_CONSTVOL; + } else if (ssModel == "PureFuild") { + type = cVPSSMGR_PUREFLUID; + } else if (ssModel == "Water_ConstVol") { + type = cVPSSMGR_WATER_CONSTVOL; + } else if (ssModel == "Water_HKFT") { + type = cVPSSMGR_WATER_HKFT; + } else if (ssModel == "General") { + type = cVPSSMGR_GENERAL; + } else { + type = cVPSSMGR_UNDEF; + } + return type; + } + + // Stub out of new capabilities. + + VPSSMgr* + VPSSMgrFactory::newVPSSMgr(VPStandardStateTP *vp_ptr, + XML_Node* phaseNode_ptr, + XML_Node* spData_node) { + std::string ssModel=""; + VPSSMgr *vpss = 0; + // First look for any explicit instructions within the XML Data + if (phaseNode_ptr) { + if (phaseNode_ptr->hasChild("thermo")) { + const XML_Node& thermoNode = phaseNode_ptr->child("thermo"); + if (thermoNode.hasChild("standardState")) { + const XML_Node& ssNode = thermoNode.child("standardState"); + ssModel = ssNode["model"]; + } + } + } + + + // first get the reference state handler + SpeciesThermo *spth = newSpeciesThermoMgr(spData_node); + vp_ptr->setSpeciesThermo(spth); + + if (ssModel != "") { + VPSSMgr_enumType type = VPSSMgr_StringConversion(ssModel); + vpss = newVPSSMgr(type, vp_ptr); + return vpss; + } + + // If it comes back as general, then there may be some unknown + // parameterizations to the SpeciesThermo factory routine. + bool haveSomeUnknowns = true; + GeneralSpeciesThermo *ttmp = dynamic_cast(spth); + if (ttmp == 0) { + haveSomeUnknowns = false; + } + + + if (vp_ptr->eosType() == cVPSS_IdealGas) { + vpss = new VPSSMgr_IdealGas(vp_ptr, spth); + + } + + if (vp_ptr->eosType() == cVPSS_ConstVol) { + vpss = new VPSSMgr_ConstVol(vp_ptr, spth); + } + + int inasa = 0, ishomate = 0, isimple = 0, iwater = 0, itpx = 0, iother = 0; + int ihptx = 0; + + try { + getVPSSMgrTypes(spData_node, inasa, ishomate, isimple, iwater, + itpx, ihptx, iother); + } catch (UnknownSpeciesThermoModel) { + iother = 1; + popError(); + } + + if (iwater == 1) { + if (ihptx == 0) { + vpss == new VPSSMgr_Water_ConstVol(vp_ptr, spth); + } else { + vpss == new VPSSMgr_Water_HKFT(vp_ptr, spth); + } + } + // The default here is to fall back to use the completely + // general representation. + if (vpss == 0) { + vpss = new VPSSMgr_General(vp_ptr, spth); + } + return vpss; + } + + VPSSMgr* + VPSSMgrFactory::newVPSSMgr(VPStandardStateTP *vp_ptr, + XML_Node* phaseNode_ptr, + std::vector spData_nodes) { + + std::string ssModel=""; + VPSSMgr *vpss = 0; + // First look for any explicit instructions within the XML Data + if (phaseNode_ptr) { + if (phaseNode_ptr->hasChild("thermo")) { + const XML_Node& thermoNode = phaseNode_ptr->child("thermo"); + if (thermoNode.hasChild("standardState")) { + const XML_Node& ssNode = thermoNode.child("standardState"); + ssModel = ssNode["model"]; + } + } + } + + // first get the reference state handler + SpeciesThermo *spth = newSpeciesThermoMgr(spData_nodes); + vp_ptr->setSpeciesThermo(spth); + + if (ssModel != "") { + VPSSMgr_enumType type = VPSSMgr_StringConversion(ssModel); + vpss = newVPSSMgr(type, vp_ptr); + return vpss; + } + + // If it comes back as general, then there may be some unknown + // parameterizations to the SpeciesThermo factory routine. + bool haveSomeUnknowns = true; + GeneralSpeciesThermo *ttmp = dynamic_cast(spth); + if (ttmp == 0) { + haveSomeUnknowns = false; + } + + if (vp_ptr->eosType() == cIdealSolnGasVPSS) { + vpss = new VPSSMgr_IdealGas(vp_ptr, spth); + } + + if (vp_ptr->eosType() == cIdealSolnGasVPSS_iscv) { + vpss = new VPSSMgr_ConstVol(vp_ptr, spth); + } + + int n = static_cast(spData_nodes.size()); + int inasa = 0, ishomate = 0, isimple = 0, iwater = 0, itpx = 0, iother = 0; + int ihptx = 0; + for (int j = 0; j < n; j++) { + try { + getVPSSMgrTypes(spData_nodes[j], inasa, ishomate, isimple, iwater, + itpx, ihptx, iother); + } catch (UnknownSpeciesThermoModel) { + iother = 1; + popError(); + } + } + if (iwater == 1) { + if (ihptx == 0) { + vpss = new VPSSMgr_Water_ConstVol(vp_ptr, spth); + } else { + vpss = new VPSSMgr_Water_HKFT(vp_ptr, spth); + } + } + if (vpss == 0) { + vpss = new VPSSMgr_General(vp_ptr, spth); + } + return vpss; + } + + + + // I don't think this is currently used. However, this is a virtual + // function where additional capabilities may be added. + VPSSMgr* + VPSSMgrFactory::newVPSSMgr(VPSSMgr_enumType type, VPStandardStateTP *vp_ptr) { + SpeciesThermo &spthermoRef = vp_ptr->speciesThermo(); + switch (type) { + case cVPSSMGR_IDEALGAS: + return new VPSSMgr_IdealGas(vp_ptr, &spthermoRef); + break; + case cVPSSMGR_CONSTVOL: + return new VPSSMgr_ConstVol(vp_ptr, &spthermoRef); + break; + case cVPSSMGR_PUREFLUID: + throw CanteraError("VPSSMgrFactory::newVPSSMgr", + "unimplemented"); + break; + case cVPSSMGR_WATER_CONSTVOL: + return new VPSSMgr_Water_ConstVol(vp_ptr, &spthermoRef); + break; + case cVPSSMGR_WATER_HKFT: + return new VPSSMgr_Water_HKFT(vp_ptr, &spthermoRef); + break; + case cVPSSMGR_GENERAL: + return new VPSSMgr_General(vp_ptr, &spthermoRef); + break; + case cVPSSMGR_UNDEF: + default: + throw UnknownVPSSMgrModel("VPSSMgrFactory::newVPSSMgr", int2str(type)); + return 0; + } + } + + // I don't think this is currently used + VPSSMgr* newVPSSMgr(VPSSMgr_enumType type, VPStandardStateTP *vp_ptr, + Cantera::VPSSMgrFactory* f) { + if (f == 0) { + f = VPSSMgrFactory::factory(); + } + VPSSMgr* vpsssptherm = f->newVPSSMgr(type, vp_ptr); + return vpsssptherm; + } + + VPSSMgr* newVPSSMgr(VPStandardStateTP *tp_ptr, + XML_Node* phaseNode_ptr, + XML_Node* spData_node, + VPSSMgrFactory* f) { + if (f == 0) { + f = VPSSMgrFactory::factory(); + } + VPSSMgr* vpsssptherm = f->newVPSSMgr(tp_ptr, phaseNode_ptr, spData_node); + return vpsssptherm; + } + + VPSSMgr* newVPSSMgr(VPStandardStateTP *tp_ptr, + XML_Node* phaseNode_ptr, + std::vector spData_nodes, + VPSSMgrFactory* f) { + if (f == 0) { + f = VPSSMgrFactory::factory(); + } + VPSSMgr* vpsssptherm = f->newVPSSMgr(tp_ptr, phaseNode_ptr, spData_nodes); + return vpsssptherm; + } + + +} diff --git a/Cantera/src/thermo/VPSSMgrFactory.h b/Cantera/src/thermo/VPSSMgrFactory.h new file mode 100644 index 000000000..9330fe34f --- /dev/null +++ b/Cantera/src/thermo/VPSSMgrFactory.h @@ -0,0 +1,276 @@ +/** + * @file VPSSMgrFactory.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::VPSSMgrFactory VPSSMgrFactory\endlink); + */ + +/* + * $Author$ + * $Revision$ + * $Date$ + */ + +/* + * Copywrite (2006) Sandia Corporation. Under the terms of + * Contract DE-AC04-94AL85000 with Sandia Corporation, the + * U.S. Government retains certain rights in this software. + */ + +#ifndef VPSSSPECIESTHERMO_FACTORY_H +#define VPSSSPECIESTHERMO_FACTORY_H + +#include "SpeciesThermo.h" +#include "ctexceptions.h" +#include "FactoryBase.h" +#include "VPSSMgr.h" + +namespace Cantera { + + class XML_Node; + class VPStandardStateTP; + + //! Throw a named error for an unknown or missing vpss species thermo model. + /*! + * + * @ingroup thermoprops + */ + class UnknownVPSSMgrModel: public CanteraError { + public: + //! Constructor + /*! + * @param proc Function name error occurred. + * @param VPSSMgrModel Unrecognized species thermo calculator name + */ + UnknownVPSSMgrModel(std::string proc, + std::string VPSSMgrModel) : + CanteraError(proc, "Specified VPSSMgr model " + + VPSSMgrModel + + " does not match any known type.") {} + //! destructor + virtual ~UnknownVPSSMgrModel() {} + }; + + //! Factory to build instances of classes that manage the + //! standard-state thermodynamic properties of a set of species. + /*! + * This class is responsible for making the decision concerning + * which derivative of VPSSMgr object to use. + * The VPSSMgr object is used to calculate + * thermodynamic functions for the standard state. + * It queries the database of species to understand what + * the requirements are for the submodels for all of the + * species in the phase. Then, it picks the derived VPSSMgr + * object to use and passes it back to the calling routine. + * It doesn't load any data into the derived + * VPSSMgr object. + * + * Making the choice of VPSSMgr types is the only + * thing this class does. + * + * 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 VPSSMgrFactory : public FactoryBase { + + 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 VPSSMgrFactory* factory() { +#if defined(THREAD_SAFE_CANTERA) + boost::mutex::scoped_lock lock(vpss_species_thermo_mutex); +#endif + if (!s_factory) s_factory = new VPSSMgrFactory; + 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. + */ + void deleteFactory() { + +#if defined(THREAD_SAFE_CANTERA) + boost::mutex::scoped_lock lock(species_thermo_mutex); +#endif + 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 ~VPSSMgrFactory() { + } + + //! String conversion to an enumType + /*! + * This routine is a string conversion. The string is obtained from the + * standardState model attribute and converted to a VPSSMgr_enumType + * type. + * + * @param ssModel String representing the VPSSMGr object + */ + virtual VPSSMgr_enumType + VPSSMgr_StringConversion(std::string ssModel) const; + + //! Create a new species variable pressure standard state calculator + /*! + * @param type The enumerated type of the standard state calculator + * @param vp_ptr Variable pressure standard state ThermoPhase object + * that will be the owner. + */ + virtual VPSSMgr* newVPSSMgr(VPSSMgr_enumType type, VPStandardStateTP *vp_ptr); + + //! 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 vp_ptr Variable pressure standard state ThermoPhase object + * that will be the owner. + * @param phaseNode_ptr Pointer to the ThermoPhase phase XML Node + * @param spData_node Pointer to a speciesData XML Node. + * Each speciesData node contains a list of XML species elements + * e.g., \ + */ + virtual VPSSMgr* newVPSSMgr(VPStandardStateTP *vp_ptr, + XML_Node* phaseNode_ptr, + 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 vp_ptr Variable pressure standard state ThermoPhase object + * that will be the owner. + * @param phaseNode_ptr Pointer to the ThermoPhase phase XML Node + * @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., \ + */ + virtual VPSSMgr* newVPSSMgr(VPStandardStateTP *vp_ptr, + XML_Node* phaseNode_ptr, + std::vector spData_nodes); + + + private: + + //! pointer to the sole instance of this class + static VPSSMgrFactory* s_factory; + +#if defined(THREAD_SAFE_CANTERA) + //! Decl of the static mutex variable that locks the + //! %VPSSMgr factory singelton + static boost::mutex vpss_species_thermo_mutex; +#endif + + //! Constructor. This is made private, so that only the static + //! method factory() can instantiate the class. + VPSSMgrFactory(){} + }; + + + ////////////////////// 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 vp_ptr Variable pressure standard state ThermoPhase object + * that will be the owner. + * @param f Pointer to a SpeciesThermoFactory. optional parameter. + * Defautls to NULL. + */ + VPSSMgr* newVPSSMgr(VPSSMgr_enumType type, + VPStandardStateTP *vp_ptr, VPSSMgrFactory* f=0); + + //! Function to return VPSSMgr 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 VPSSMgrFactory. + * + * @param vp_ptr Variable pressure standard state ThermoPhase object + * that will be the owner. + * @param phaseNode_ptr Pointer to the ThermoPhase phase XML Node + * @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., \ + * @param f Pointer to a SpeciesThermoFactory. optional parameter. + * Defautls to NULL. + */ + VPSSMgr* newVPSSMgr(VPStandardStateTP *vp_ptr, + XML_Node* phaseNode_ptr, + XML_Node* spData_node, + VPSSMgrFactory* f=0); + + //! Function to return VPSSMgr manager + /*! + * This utility program will look through species nodes. It will discover what + * each species needs for its species property managers. Then, + * it will alloc and return the proper species property manager to use. + * + * These functions allow using a different factory class that + * derives from SpeciesThermoFactory. + * + * @param vp_ptr Variable pressure standard state ThermoPhase object + * that will be the owner. + * @param phaseNode_ptr Pointer to the ThermoPhase phase XML Node + * @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., \ + * @param f Pointer to a SpeciesThermoFactory. optional parameter. + * Defautls to NULL. + */ + VPSSMgr* newVPSSMgr(VPStandardStateTP *vp_ptr, + XML_Node* phaseNode_ptr, + std::vector spData_nodes, + VPSSMgrFactory* f=0); + +} + +#endif + + diff --git a/Cantera/src/thermo/VPSSMgr_ConstVol.cpp b/Cantera/src/thermo/VPSSMgr_ConstVol.cpp new file mode 100644 index 000000000..8f419c7d9 --- /dev/null +++ b/Cantera/src/thermo/VPSSMgr_ConstVol.cpp @@ -0,0 +1,164 @@ +/** + * @file VPSSMgr_ConstVol.cpp + * Definition file for a derived class that handles the calculation + * of standard state thermo properties for + * a set of species which have a constant molar volume pressure + * dependence (see \ref thermoprops and + * class \link Cantera::VPSSMgr_ConstVol VPSSMgr_ConstVol\endlink). + */ +/* + * 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 "VPSSMgr_ConstVol.h" +#include "xml.h" +#include "VPStandardStateTP.h" +#include "SpeciesThermoFactory.h" +#include "PDSS_ConstVol.h" + +using namespace std; + +namespace Cantera { + + VPSSMgr_ConstVol::VPSSMgr_ConstVol(VPStandardStateTP *vp_ptr, SpeciesThermo *spth) : + VPSSMgr(vp_ptr, spth) + { + m_useTmpRefStateStorage = true; + m_useTmpStandardStateStorage = true; + } + + + VPSSMgr_ConstVol::~VPSSMgr_ConstVol() + { + } + + VPSSMgr_ConstVol::VPSSMgr_ConstVol(const VPSSMgr_ConstVol &right) : + VPSSMgr(right.m_vptp_ptr, right.m_spthermo) + { + m_useTmpRefStateStorage = true; + m_useTmpStandardStateStorage = true; + *this = right; + } + + + VPSSMgr_ConstVol& VPSSMgr_ConstVol::operator=(const VPSSMgr_ConstVol &b) + { + if (&b == this) return *this; + VPSSMgr::operator=(b); + return *this; + } + + VPSSMgr *VPSSMgr_ConstVol::duplMyselfAsVPSSMgr() const { + VPSSMgr_ConstVol *vpm = new VPSSMgr_ConstVol(*this); + return (VPSSMgr *) vpm; + } + + /* + * Get the nondimensional Entropies for the species + * standard states at the current T and P of the solution. + * + * Note, this is equal to the reference state entropies + * due to the zero volume expansivity: + * i.e., (dS/dp)_T = (dV/dT)_P = 0.0 + */ + void VPSSMgr_ConstVol::_updateStandardStateThermo() { + + doublereal del_pRT = (m_plast - m_p0) / (GasConstant * m_tlast); + + for (int k = 0; k < m_kk; k++) { + m_hss_RT[k] = m_h0_RT[k] + del_pRT * m_Vss[k]; + m_cpss_R[k] = m_cp0_R[k]; + m_sss_R[k] = m_s0_R[k]; + m_gss_RT[k] = m_hss_RT[k] - m_sss_R[k]; + // m_Vss[k] constant + } + } + + void VPSSMgr_ConstVol::initThermo() { + VPSSMgr::initThermo(); + } + + void + VPSSMgr_ConstVol::initThermoXML(XML_Node& phaseNode, std::string id) { + VPSSMgr::initThermoXML(phaseNode, id); + + XML_Node& speciesList = phaseNode.child("speciesArray"); + XML_Node* speciesDB = get_XML_NameID("speciesData", speciesList["datasrc"], + &phaseNode.root()); + const vector&sss = m_vptp_ptr->speciesNames(); + + for (int k = 0; k < m_kk; k++) { + const XML_Node* s = speciesDB->findByAttr("name", sss[k]); + if (!s) { + throw CanteraError("VPSSMgr_ConstVol::initThermoXML", + "no species Node for species " + sss[k]); + } + const XML_Node *ss = s->findByName("standardState"); + if (!ss) { + throw CanteraError("VPSSMgr_ConstVol::initThermoXML", + "no standardState Node for species " + s->name()); + } + std::string model = (*ss)["model"]; + if (model != "constant_incompressible") { + throw CanteraError("VPSSMgr_ConstVol::initThermoXML", + "standardState model for species isn't constant_incompressible: " + s->name()); + } + m_Vss[k] = getFloat(*ss, "molarVolume", "-"); + } + } + + // void + // VPSSMgr_ConstVol::installSpecies(int k, const XML_Node& speciesNode, + // const XML_Node *phaseNode_ptr) { + //} + + PDSS * + VPSSMgr_ConstVol::createInstallPDSS(int k, const XML_Node& speciesNode, + const XML_Node *phaseNode_ptr) { + //VPSSMgr::installSpecies(k, speciesNode, phaseNode_ptr); + const XML_Node *ss = speciesNode.findByName("standardState"); + if (!ss) { + throw CanteraError("VPSSMgr_ConstVol::installSpecies", + "no standardState Node for species " + speciesNode.name()); + } + std::string model = (*ss)["model"]; + if (model != "constant_incompressible") { + throw CanteraError("VPSSMgr_ConstVol::initThermoXML", + "standardState model for species isn't " + "constant_incompressible: " + speciesNode.name()); + } + if ((int) m_Vss.size() < k+1) { + m_Vss.resize(k+1, 0.0); + } + m_Vss[k] = getFloat(*ss, "molarVolume", "-"); + + installSTSpecies(k, speciesNode, phaseNode_ptr); + + + PDSS *kPDSS = new PDSS_ConstVol(m_vptp_ptr, k, speciesNode, + *phaseNode_ptr, true); + return kPDSS; + } + + PDSS_enumType VPSSMgr_ConstVol::reportPDSSType(int k) const { + return cPDSS_CONSTVOL; + } + + VPSSMgr_enumType VPSSMgr_ConstVol::reportVPSSMgrType() const { + return cVPSSMGR_CONSTVOL; + } +} + diff --git a/Cantera/src/thermo/VPSSMgr_ConstVol.h b/Cantera/src/thermo/VPSSMgr_ConstVol.h new file mode 100644 index 000000000..bc23f2dee --- /dev/null +++ b/Cantera/src/thermo/VPSSMgr_ConstVol.h @@ -0,0 +1,207 @@ +/** + * @file VPSSMgr_ConstVol.h + * Declarations for a derived class for the calculation of multiple-species thermodynamic + * property managers for variable temperature and pressure standard + * states assuming constant volume (see class + * \link Cantera::VPSSMgr_ConstVol VPSSMgr_ConstVol \endlink). + */ +/* + * $Author$ + * $Revision$ + * $Date$ + */ +/* + * 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. + */ + +#ifndef CT_VPSSMGR_CONSTVOL_H +#define CT_VPSSMGR_CONSTVOL_H + +#include "ct_defs.h" +#include "VPSSMgr.h" + +namespace Cantera { + + class SpeciesThermoInterpType; + class PDSS; + + //! Constant Molar Volume e VPSS species thermo manager class + /*! + * The calculation of multiple-species thermodynamic + * property managers for variable temperature and pressure standard + * states assuming a constant partial molar volume assumption. + */ + class VPSSMgr_ConstVol : public VPSSMgr { + + public: + + //! Constructor + /*! + * @param vp_ptr Pointer to the owning VPStandardStateTP object + * for the phase. It's a requirement that this be + * already malloced. + * @param spth Pointer to the SpeciesThermo object for the + * phase. It's a requirement that this be already + * malloced. + */ + VPSSMgr_ConstVol(VPStandardStateTP *vp_ptr, SpeciesThermo *spth); + + //! Destructor + virtual ~VPSSMgr_ConstVol(); + + //! Copy Constructor + /*! + * @param right Reference to %VPSSMgr_ConstVol object to be copied into the + * current one. + */ + VPSSMgr_ConstVol(const VPSSMgr_ConstVol &right); + + //! Assignment operator for the %VPSSMgr_ConstVol object + /*! + * This is NOT a virtual function. + * + * @param right Reference to %VPSSMgr_ConstVol object to be copied into the + * current one. + */ + VPSSMgr_ConstVol& operator=(const VPSSMgr_ConstVol &right); + + //! Duplicator routine for the VPSSMgr base class + /*! + * This virtual routine can be used to duplicate %VPSSMgr objects + * inherited from %VPSSMgr even if the application only has + * a pointer to %VPSSMgr to work with. + */ + virtual VPSSMgr *duplMyselfAsVPSSMgr() const; + + /*! + * @name Properties of the Standard State of the Species in the Solution + * + * Within VPStandardStateTP, these properties are calculated via a common routine, + * _updateStandardStateThermo(), + * which must be overloaded in inherited objects. + * The values are cached within this object, and are not recalculated unless + * the temperature or pressure changes. + */ + //@{ + + protected: + + //! Updates the standard state thermodynamic functions at the current + //! T and P of the solution. + /*! + * @internal + * + * If m_useTmpStandardStateStorage is true, + * this function must be called whenever the temperature or pressure + * has changed. + * + * This function is responsible for updating the following internal members, + * when m_useTmpStandardStateStorage is true. + * + * - m_hss_RT; + * - m_cpss_R; + * - m_gss_RT; + * - m_sss_R; + * - m_Vss + * + * If m_useTmpStandardStateStorage is not true, this function may be + * required to be called every time information is requested from + * this object. + */ + virtual void _updateStandardStateThermo(); + + //@} + + /// @name Thermodynamic Values for the Species Reference States + /*! + * There are also temporary + * variables for holding the species reference-state values of Cp, H, S, and V at the + * last temperature and reference pressure called. These functions are not recalculated + * if a new call is made using the previous temperature. + * All calculations are done within the routine _updateRefStateThermo(). + * _updateRefStateThermo() is defined in the parent object. + */ + //@{ + //@} + + //! @name Initialization Methods - For Internal use + /*! + * The following methods are used in the process of constructing + * the phase and setting its parameters from a specification in an + * input file. They are not normally seen by application programs + */ + //@{ + + public: + //! Initialize the VPSSMgr object + /*! + * 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. It is called after createInstallPDSS() and + * before initThermoXML(). + * + * @internal + */ + virtual void initThermo(); + + //! Initialize the thermo for this standard state thermo calculator + /*! + * This task is done last, after createInstallPDSS() and after + * initThermo(). + * + * @param phaseNode Reference to the phase node in the XML tree + * @param id string name of the phase + */ + virtual void initThermoXML(XML_Node& phaseNode, std::string id); + + //! Create and install a constant volume pressure dependent + //! standard state for one species within this object + /*! + * This function sets up the internal data within this object for + * handling the calculation of the standard state for the species. + * + * - It registers the species with the SpeciesThermo object for the + * containing VPStandardStateTP phase. + * - It grabs the molar volume property and installs its value within + * this object. + * - It also creates a PDSS object, which basically contains a + * duplication of some of this information and returns a pointer to + * the new object. + * . + * + * @param k Species index within the phase + * @param speciesNode Reference to the species node in the XML tree + * @param phaseNode_ptr Pointer to the phase node in the XML tree + * + * @return Returns a pointer to the a newly malloced PDSS object + * containing the parameterization + */ + virtual PDSS* createInstallPDSS(int k, const XML_Node& speciesNode, + const XML_Node *phaseNode_ptr); + //@} + + //! This utility function reports the type of parameterization + //! used for the species with index number index. + /*! + * + * @param index Species index + */ + virtual PDSS_enumType reportPDSSType(int index = -1) const ; + + + //! This utility function reports the type of manager + //! for the calculation of ss properties + /*! + * + */ + virtual VPSSMgr_enumType reportVPSSMgrType() const ; + + }; + //@} +} + +#endif diff --git a/Cantera/src/thermo/VPSSMgr_General.cpp b/Cantera/src/thermo/VPSSMgr_General.cpp new file mode 100644 index 000000000..f0f00ed52 --- /dev/null +++ b/Cantera/src/thermo/VPSSMgr_General.cpp @@ -0,0 +1,168 @@ +/** + * @file VPSSMgr_General.cpp + * Definition file for a derived class that handles the calculation + * of standard state thermo properties for + * a set of species belonging to a single phase in a completely general + * but slow way (see \ref thermoprops and + * class \link Cantera::VPSSMgr_General VPSSMgr_General\endlink). + */ +/* + * 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 "VPSSMgr_General.h" +#include "PDSS.h" +#include "xml.h" +#include "ctml.h" +#include "PDSS_IdealGas.h" +#include "PDSS_Water.h" +#include "PDSS_ConstVol.h" + +using namespace std; + +namespace Cantera { + + + VPSSMgr_General::VPSSMgr_General(VPStandardStateTP *vp_ptr, + SpeciesThermo *spth) : + VPSSMgr(vp_ptr, spth) + { + // Might want to do something other than holding this true. + // However, for the sake of getting this all up and running, + // will not go there for now. + m_useTmpStandardStateStorage = true; + m_useTmpRefStateStorage = true; + } + + + VPSSMgr_General::~VPSSMgr_General() + { + } + + VPSSMgr_General::VPSSMgr_General(const VPSSMgr_General &right) : + VPSSMgr(right.m_vptp_ptr, right.m_spthermo) + { + m_useTmpStandardStateStorage = true; + m_useTmpRefStateStorage = true; + *this = right; + } + + + VPSSMgr_General& VPSSMgr_General::operator=(const VPSSMgr_General &b) + { + if (&b == this) return *this; + VPSSMgr::operator=(b); + return *this; + } + + VPSSMgr *VPSSMgr_General::duplMyselfAsVPSSMgr() const { + VPSSMgr_General *vpm = new VPSSMgr_General(*this); + return (VPSSMgr *) vpm; + } + + + + void VPSSMgr_General::_updateRefStateThermo() const + { + for (int k = 0; k < m_kk; k++) { + PDSS *kPDSS = m_PDSS_ptrs[k]; + kPDSS->setState_TP(m_tlast, m_plast); + m_h0_RT[k] = kPDSS->enthalpy_RT_ref(); + m_s0_R[k] = kPDSS->entropy_R_ref(); + m_g0_RT[k] = m_h0_RT[k] - m_s0_R[k]; + m_cp0_R[k] = kPDSS->cp_R_ref(); + m_V0[k] = kPDSS->molarVolume_ref(); + } + } + + + void VPSSMgr_General::_updateStandardStateThermo() + { + for (int k = 0; k < m_kk; k++) { + PDSS *kPDSS = m_PDSS_ptrs[k]; + kPDSS->setState_TP(m_tlast, m_plast); + m_hss_RT[k] = kPDSS->enthalpy_RT(); + m_sss_R[k] = kPDSS->entropy_R(); + m_gss_RT[k] = m_hss_RT[k] - m_sss_R[k]; + m_cpss_R[k] = kPDSS->cp_R(); + m_Vss[k] = kPDSS->molarVolume(); + } + } + + + void VPSSMgr_General::initThermo() { + initLengths(); + } + + + void + VPSSMgr_General::initThermoXML(XML_Node& phaseNode, std::string id) { + VPSSMgr::initThermoXML(phaseNode, id); + + } + + PDSS* + VPSSMgr_General::returnPDSS_ptr(int k, const XML_Node& speciesNode, + const XML_Node *phaseNode_ptr, bool &doST) { + PDSS *kPDSS = 0; + doST = true; + + const XML_Node * const ss = speciesNode.findByName("standardState"); + if (!ss) { + VPSSMgr::installSTSpecies(k, speciesNode, phaseNode_ptr); + kPDSS = new PDSS_IdealGas(m_vptp_ptr, k, speciesNode, *phaseNode_ptr, true); + return kPDSS; + } + std::string model = (*ss)["model"]; + if (model == "constant_incompressible") { + VPSSMgr::installSTSpecies(k, speciesNode, phaseNode_ptr); + kPDSS = new PDSS_ConstVol(m_vptp_ptr, k, speciesNode, *phaseNode_ptr, true); + } else if (model == "waterIAPWS" || model == "waterPDSS") { + doST = false; + kPDSS = new PDSS_Water(); + } else { + throw CanteraError("VPSSMgr_General::returnPDSS_ptr", + "unknown"); + } + return kPDSS; + } + + PDSS * + VPSSMgr_General::createInstallPDSS(int k, const XML_Node& speciesNode, + const XML_Node *phaseNode_ptr) { + bool doST; + PDSS *kPDSS = returnPDSS_ptr(k, speciesNode, phaseNode_ptr, doST); + // VPSSMgr::installSTSpecies(k, speciesNode, phaseNode_ptr); + if ((int) m_PDSS_ptrs.size() < k+1) { + m_PDSS_ptrs.resize(k+1, 0); + } + + m_PDSS_ptrs[k] = kPDSS; + return kPDSS; + } + + PDSS_enumType VPSSMgr_General::reportPDSSType(int k) const { + PDSS *kPDSS = m_PDSS_ptrs[k]; + return kPDSS->reportPDSSType(); + } + + + VPSSMgr_enumType VPSSMgr_General::reportVPSSMgrType() const { + return cVPSSMGR_GENERAL; + } +} + + diff --git a/Cantera/src/thermo/VPSSMgr_General.h b/Cantera/src/thermo/VPSSMgr_General.h new file mode 100644 index 000000000..7fdd6e562 --- /dev/null +++ b/Cantera/src/thermo/VPSSMgr_General.h @@ -0,0 +1,224 @@ +/** + * @file VPSSMgr_General.h + * Declaration file for a derived class that handles the calculation + * of standard state thermo properties for + * a set of species belonging to a single phase in a completely general + * but slow way (see \ref thermoprops and + * class \link Cantera::VPSSMgr_General VPSSMgr_General\endlink). + */ +/* + * $Author$ + * $Revision$ + * $Date$ + */ +/* + * Copywrite (2007) Sandia Corporation. Under the terms of + * Contract DE-AC04-94AL85000 with Sandia Corporation, the + * U.S. Government retains certain rights in this software. + */ + +#ifndef CT_VPSSMGR_GENERAL_H +#define CT_VPSSMGR_GENERAL_H + +#include "ct_defs.h" +#include "VPSSMgr.h" + +namespace Cantera { + + class SpeciesThermoInterpType; + class VPStandardStateTP; + class SpeciesThermo; + class PDSS; + + + //! Class that handles the calculation of standard state thermo properties for + //! a set of species belonging to a single phase in a completely general + //! but slow way + /*! + * This class manages the calculation standard state thermo properties for + * a set of species belonging to a single phase in a completely general + * but slow way. + * The way this does this is to call the underlying PDSS routines one at a + * time for every species. + */ + class VPSSMgr_General : public VPSSMgr { + + public: + + //! Constructor + /*! + * @param vp_ptr Pointer to the owning VPStandardStateTP object + * for the phase. It's a requirement that this be + * already malloced. + * @param spth Pointer to the SpeciesThermo object for the + * phase. It's a requirement that this be already + * malloced. + */ + VPSSMgr_General(VPStandardStateTP *vp_ptr, + SpeciesThermo *spth); + + //! Destructor + virtual ~VPSSMgr_General(); + + //! Copy Constructor for the %SpeciesThermo object. + /*! + * @param right Reference to %SpeciesThermo object to be copied into the + * current one. + */ + VPSSMgr_General(const VPSSMgr_General &right); + + //! Assignment operator for the %SpeciesThermo object + /*! + * This is NOT a virtual function. + * + * @param right Reference to %SpeciesThermo object to be copied into the + * current one. + */ + VPSSMgr_General& operator=(const VPSSMgr_General &right); + + //! Duplication routine for objects which inherit from + //! %VPSSSpeciesThermo + /*! + * This virtual routine can be used to duplicate %VPSSSpeciesThermo objects + * inherited from %VPSSSpeciesThermo even if the application only has + * a pointer to %VPSSSpeciesThermo to work with. + */ + virtual VPSSMgr *duplMyselfAsVPSSMgr() const; + + /*! + * @name Properties of the Standard State of the Species in the Solution + * + * Within VPStandardStateTP, these properties are calculated via a common routine, + * _updateStandardStateThermo(), + * which must be overloaded in inherited objects. + * The values are cached within this object, and are not recalculated unless + * the temperature or pressure changes. + */ + //@{ + + + protected: + + //! Internally updates the standard state thermodynamic functions at the current + //! T and P of the solution. + /*! + * @internal + * + * If m_useTmpStandardStateStorage is true, + * this function must be called whenever the temperature or pressure + * has changed. + * + * This function is responsible for updating the following internal members, + * when m_useTmpStandardStateStorage is true. + * + * - m_hss_RT; + * - m_cpss_R; + * - m_gss_RT; + * - m_sss_R; + * - m_Vss + * + * If m_useTmpStandardStateStorage is not true, this function may be + * required to be called every time information is requested from + * this object. + * + * Underscore updates never check for the state of the system + * They just do the calculation. + */ + virtual void _updateStandardStateThermo(); + + //! Updates the reference state thermodynamic functions at the + //! current T of the solution and the reference pressure + /*! + * Underscore updates never check for the state of the system + * They just do the calculation. + */ + virtual void _updateRefStateThermo () const; + + //@} + /// @name Thermodynamic Values for the Species Reference States (VPStandardStateTP) + /*! + * There are also temporary + * variables for holding the species reference-state values of Cp, H, S, and V at the + * last temperature and reference pressure called. These functions are not recalculated + * if a new call is made using the previous temperature. + * All calculations are done within the routine _updateRefStateThermo(). + */ + //@{ + + + //! @name Initialization Methods - For Internal use (VPStandardState) + /*! + * The following methods are used in the process of constructing + * the phase and setting its parameters from a specification in an + * input file. They are not normally used in application programs. + * To see how they are used, see files importCTML.cpp and + * ThermoFactory.cpp. + */ + //@{ + + + //! @internal Initialize the object + /*! + * 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 + */ + virtual void initThermo(); + + virtual void initThermoXML(XML_Node& phaseNode, std::string id); + + PDSS* returnPDSS_ptr(int k, const XML_Node& speciesNode, + const XML_Node *phaseNode_ptr, bool &doST); + + virtual PDSS *createInstallPDSS(int k, const XML_Node& speciesNode, + const XML_Node *phaseNode_ptr); + + //! This utility function reports the type of parameterization + //! used for the species with index number index. + /*! + * + * @param index Species index + */ + virtual PDSS_enumType reportPDSSType(int index = -1) const ; + + + //! This utility function reports the type of manager + //! for the calculation of the standard state properties + /*! + * + */ + virtual VPSSMgr_enumType reportVPSSMgrType() const ; + + + protected: + + //! Shallow pointers containing the PDSS objects for the species + //! in this phase. + /*! + * This object doesn't own these pointers. + */ + std::vector m_PDSS_ptrs; + + private: + + //! VPStandardStateTP has its own err routine + /*! + * @param msg Error message string + */ + doublereal err(std::string msg) const; + + + }; + //@} +} + +#endif + diff --git a/Cantera/src/thermo/VPSSMgr_IdealGas.cpp b/Cantera/src/thermo/VPSSMgr_IdealGas.cpp new file mode 100644 index 000000000..7df76b254 --- /dev/null +++ b/Cantera/src/thermo/VPSSMgr_IdealGas.cpp @@ -0,0 +1,140 @@ +/** + * @file VPSSMgr_IdealGas.cpp + * Definition file for a derived class that handles the calculation + * of standard state thermo properties for + * a set of species which have an Ideal Gas dependence + * (see \ref thermoprops and + * class \link Cantera::VPSSMgr_IdealGas VPSSMgr_IdealGas\endlink). + */ +/* + * 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 "VPSSMgr_IdealGas.h" +#include "utilities.h" +#include "xml.h" +#include "ctml.h" +#include "SpeciesThermoFactory.h" +#include "PDSS_IdealGas.h" + +using namespace std; +using namespace ctml; + +namespace Cantera { + + VPSSMgr_IdealGas::VPSSMgr_IdealGas(VPStandardStateTP *vp_ptr, SpeciesThermo *spth) : + VPSSMgr(vp_ptr, spth) + { + m_useTmpRefStateStorage = true; + m_useTmpStandardStateStorage = true; + } + + + VPSSMgr_IdealGas::~VPSSMgr_IdealGas() + { + } + + VPSSMgr_IdealGas::VPSSMgr_IdealGas(const VPSSMgr_IdealGas &right) : + VPSSMgr(right.m_vptp_ptr, right.m_spthermo) + { + m_useTmpRefStateStorage = true; + m_useTmpStandardStateStorage = true; + *this = right; + } + + + VPSSMgr_IdealGas& VPSSMgr_IdealGas::operator=(const VPSSMgr_IdealGas &b) + { + if (&b == this) return *this; + VPSSMgr::operator=(b); + return *this; + } + + VPSSMgr *VPSSMgr_IdealGas::duplMyselfAsVPSSMgr() const { + VPSSMgr_IdealGas *vpm = new VPSSMgr_IdealGas(*this); + return (VPSSMgr *) vpm; + } + + + void VPSSMgr_IdealGas::getIntEnergy_RT(doublereal* urt) const { + getEnthalpy_RT(urt); + for (int k = 0; k < m_kk; k++) { + urt[k] -= 1.0; + } + } + + void VPSSMgr_IdealGas::getStandardVolumes(doublereal* vol) const + { + copy(m_Vss.begin(), m_Vss.end(), vol); + } + + void VPSSMgr_IdealGas::_updateStandardStateThermo() { + + doublereal pp = log(m_plast / m_p0); + doublereal v = temperature() *GasConstant /m_plast; + + for (int k = 0; k < m_kk; k++) { + m_hss_RT[k] = m_h0_RT[k]; + m_cpss_R[k] = m_cp0_R[k]; + m_sss_R[k] = m_s0_R[k] - pp; + m_gss_RT[k] = m_hss_RT[k] - m_sss_R[k]; + m_Vss[k] = v; + } + } + + void + VPSSMgr_IdealGas::initThermoXML(XML_Node& phaseNode, std::string id) { + VPSSMgr::initThermoXML(phaseNode, id); + } + + PDSS * + VPSSMgr_IdealGas::createInstallPDSS(int k, const XML_Node& speciesNode, + const XML_Node *phaseNode_ptr) { + //VPSSMgr::installSpecies(k, speciesNode, phaseNode_ptr); + const XML_Node *ss = speciesNode.findByName("standardState"); + if (ss) { + std::string model = (*ss)["model"]; + if (model != "ideal_gas") { + throw CanteraError("VPSSMgr_IdealGas::initThermoXML", + "standardState model for species isn't " + "ideal_gas: " + speciesNode.name()); + } + } + if ((int) m_Vss.size() < k+1) { + m_Vss.resize(k+1, 0.0); + } + + SpeciesThermoFactory* f = SpeciesThermoFactory::factory(); + f->installThermoForSpecies(k, speciesNode, *m_spthermo, phaseNode_ptr); + + PDSS *kPDSS = new PDSS_IdealGas(m_vptp_ptr, k, speciesNode, + *phaseNode_ptr, true); + + m_p0 = m_spthermo->refPressure(k); + return kPDSS; + } + + + PDSS_enumType VPSSMgr_IdealGas::reportPDSSType(int k) const { + return cPDSS_IDEALGAS; + } + + + VPSSMgr_enumType VPSSMgr_IdealGas::reportVPSSMgrType() const { + return cVPSSMGR_IDEALGAS; + } + +} diff --git a/Cantera/src/thermo/VPSSMgr_IdealGas.h b/Cantera/src/thermo/VPSSMgr_IdealGas.h new file mode 100644 index 000000000..3bd2df6b9 --- /dev/null +++ b/Cantera/src/thermo/VPSSMgr_IdealGas.h @@ -0,0 +1,229 @@ +/** + * @file VPSSMgr_IdealGas.h + * Declaration file for a derived class that handles the calculation + * of standard state thermo properties for + * a set of species which have an Ideal Gas dependence + * (see \ref thermoprops and + * class \link Cantera::VPSSMgr_IdealGas VPSSMgr_IdealGas\endlink). + */ +/* + * $Author$ + * $Revision$ + * $Date$ + */ + +/* + * 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. + */ + +#ifndef CT_VPSSMGR_IDEALGAS_H +#define CT_VPSSMGR_IDEALGAS_H + +#include "ct_defs.h" +#include "PDSS.h" +#include "VPSSMgr.h" + +namespace Cantera { + + class SpeciesThermoInterpType; + class VPStandardStateTP; + class SpeciesThermo; + + + //! Virtual base class for the species thermo manager classes. + /*! + * This class defines the interface which all subclasses must implement. + * + * Class %VPSSSpeciesThermo 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 VPSSMgr_IdealGas : public VPSSMgr { + + public: + + + //! Basic constructor that initializes the object + /*! + * @param vp_ptr Pointer to the owning ThermoPhase + * @param spth Species thermo pointer. + */ + VPSSMgr_IdealGas(VPStandardStateTP *vp_ptr, SpeciesThermo *spth); + + //! Destructor + virtual ~VPSSMgr_IdealGas(); + + //! Copy Constructor for the %SpeciesThermo object. + /*! + * @param right Reference to %SpeciesThermo object to be copied into the + * current one. + */ + VPSSMgr_IdealGas(const VPSSMgr_IdealGas &right); + + //! Assignment operator for the %SpeciesThermo object + /*! + * This is NOT a virtual function. + * + * @param right Reference to %SpeciesThermo object to be copied into the + * current one. + */ + VPSSMgr_IdealGas& operator=(const VPSSMgr_IdealGas &right); + + //! Duplication routine for objects which inherit from + //! %VPSSSpeciesThermo + /*! + * This virtual routine can be used to duplicate %VPSSSpeciesThermo objects + * inherited from %VPSSSpeciesThermo even if the application only has + * a pointer to %VPSSSpeciesThermo to work with. + */ + virtual VPSSMgr *duplMyselfAsVPSSMgr() const; + + /*! + * @name Properties of the Standard State of the Species in the Solution + * + * Within VPStandardStateTP, these properties are calculated via a common routine, + * _updateStandardStateThermo(), + * which must be overloaded in inherited objects. + * The values are cached within this object, and are not recalculated unless + * the temperature or pressure changes. + */ + //@{ + + /** + * Returns the vector of nondimensional + * internal Energies of the standard state at the current temperature + * and pressure of the solution for each species. + * \f[ + * u^{ss}_k(T,P) = h^{ss}_k(T) - P * V^{ss}_k + * \f] + * + * @param urt Output vector of nondimensional standard state + * internal energies. length = m_kk. + */ + virtual void getIntEnergy_RT(doublereal *urt) const; + + /** + * Get the molar volumes of each species in their standard + * states at the current + * T and P of the solution. + * units = m^3 / kmol + * + * This is redefined here to call the internal function, _updateStandardStateThermo(), + * which calculates all standard state properties at the same time. + * + * @param vol Output vector of species volumes. length = m_kk. + * units = m^3 / kmol + */ + virtual void getStandardVolumes(doublereal *vol) const; + + protected: + + //! Updates the standard state thermodynamic functions at the current + //! T and P of the solution. + /*! + * @internal + * + * If m_useTmpStandardStateStorage is true, + * this function must be called every time the temperature or pressure + * has changed. + * + * This function is responsible for updating the following internal members, + * when m_useTmpStandardStateStorage is true. + * + * - m_hss_RT; + * - m_cpss_R; + * - m_gss_RT; + * - m_sss_R; + * - m_Vss + * + * If m_useTmpStandardStateStorage is not true, this function may be + * required to be called everytime this class is invoked. + * + */ + virtual void _updateStandardStateThermo(); + + public: + + //@} + /// @name Thermodynamic Values for the Species Reference States (VPStandardStateTP) + /*! + * There are also temporary + * variables for holding the species reference-state values of Cp, H, S, and V at the + * last temperature and reference pressure called. These functions are not recalculated + * if a new call is made using the previous temperature. + * All calculations are done within the routine _updateRefStateThermo(). + */ + //@{ + + + + //! @name Initialization Methods - For Internal use (VPStandardState) + /*! + * The following methods are used in the process of constructing + * the phase and setting its parameters from a specification in an + * input file. They are not normally used in application programs. + * To see how they are used, see files importCTML.cpp and + * ThermoFactory.cpp. + * + */ + //@{ + + //! Initialize the thermo for this standard state thermo calculator + /*! + * This task is done last, after createInstallPDSS() and after + * initThermo(). + * + * @param phaseNode Reference to the phase node in the XML tree + * @param id string name of the phase + */ + virtual void initThermoXML(XML_Node& phaseNode, std::string id); + + //! Create and install an ideal gas standard state manager + //! for one species within this object + /*! + * This function sets up the internal data within this object for + * handling the calculation of the standard state for the species. + * + * - It registers the species with the SpeciesThermo object for the + * containing VPStandardStateTP phase. + * - It also creates a PDSS object, which basically contains a + * duplication of some of this information and returns a pointer to + * the new object. + * . + * @param k Species index within the phase + * @param speciesNode Reference to the species node in the XML tree + * @param phaseNode_ptr Pointer to the phase node in the XML tree + * + * @return Returns a pointer to the a newly malloced PDSS object + * containing the parameterization + */ + virtual PDSS* createInstallPDSS(int k, const XML_Node& speciesNode, + const XML_Node *phaseNode_ptr); + + + //! This utility function reports the type of parameterization + //! used for the species with index number index. + /*! + * + * @param index Species index + */ + virtual PDSS_enumType reportPDSSType(int index = -1) const ; + + + //! This utility function reports the type of manager + //! for the calculation of standard state properties + /*! + * + */ + virtual VPSSMgr_enumType reportVPSSMgrType() const ; + + }; + //@} +} + +#endif + diff --git a/Cantera/src/thermo/VPSSMgr_Water_ConstVol.cpp b/Cantera/src/thermo/VPSSMgr_Water_ConstVol.cpp new file mode 100644 index 000000000..f1980f899 --- /dev/null +++ b/Cantera/src/thermo/VPSSMgr_Water_ConstVol.cpp @@ -0,0 +1,298 @@ +/** + * @file VPSSMgr_Water_ConstVol.cpp + * Definition file for a derived class that handles the calculation + * of standard state thermo properties for pure water and + * a set of species which have a constant molar volume pressure + * dependence. + * (see \ref thermoprops and class + * \link Cantera::VPSSMgr_Water_ConstVol VPSSMgr_Water_ConstVol\endlink). + */ +/* + * 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 "VPSSMgr_Water_ConstVol.h" +#include "xml.h" +#include "VPStandardStateTP.h" +#include "PDSS_Water.h" +#include "PDSS_ConstVol.h" + +using namespace std; + +namespace Cantera { + + VPSSMgr_Water_ConstVol::VPSSMgr_Water_ConstVol(VPStandardStateTP *vp_ptr, + SpeciesThermo *spth) : + VPSSMgr(vp_ptr, spth), + m_waterSS(0) + { + m_useTmpRefStateStorage = true; + m_useTmpStandardStateStorage = true; + } + + + VPSSMgr_Water_ConstVol::~VPSSMgr_Water_ConstVol() + { + } + + VPSSMgr_Water_ConstVol::VPSSMgr_Water_ConstVol(const VPSSMgr_Water_ConstVol &right) : + VPSSMgr(right.m_vptp_ptr, right.m_spthermo) + { + m_useTmpRefStateStorage = true; + m_useTmpStandardStateStorage = true; + *this = right; + } + + + VPSSMgr_Water_ConstVol& + VPSSMgr_Water_ConstVol::operator=(const VPSSMgr_Water_ConstVol &b) + { + if (&b == this) return *this; + VPSSMgr::operator=(b); + //if (m_waterSS) delete m_waterSS; + return *this; + } + + VPSSMgr * + VPSSMgr_Water_ConstVol::duplMyselfAsVPSSMgr() const { + VPSSMgr_Water_ConstVol *vpm = new VPSSMgr_Water_ConstVol(*this); + return (VPSSMgr *) vpm; + } + + void + VPSSMgr_Water_ConstVol::initAllPtrs(VPStandardStateTP *vp_ptr, + SpeciesThermo *sp_ptr) { + VPSSMgr::initAllPtrs(vp_ptr, sp_ptr); + m_waterSS = dynamic_cast(m_vptp_ptr->providePDSS(0)); + if (!m_waterSS) { + throw CanteraError("VPSSMgr_Water_ConstVol::initAllPtrs", + "bad dynamic cast"); + } + } + + + void + VPSSMgr_Water_ConstVol::getEnthalpy_RT_ref(doublereal *hrt) const{ + // Everything should be OK except for the water SS + if (m_p0 != m_plast) { + doublereal RT = GasConstant * m_tlast; + m_waterSS->setState_TP(m_tlast, m_p0); + m_h0_RT[0] = (m_waterSS->enthalpy_mole()) / RT; + m_waterSS->setState_TP(m_tlast, m_plast); + } else { + m_h0_RT[0] = m_hss_RT[0]; + } + copy(m_h0_RT.begin(), m_h0_RT.end(), hrt); + } + + void + VPSSMgr_Water_ConstVol::getGibbs_RT_ref(doublereal *grt) const{ + // Everything should be OK except for the water SS + if (m_p0 != m_plast) { + doublereal RT = GasConstant * m_tlast; + m_waterSS->setState_TP(m_tlast, m_p0); + m_g0_RT[0] = (m_waterSS->gibbs_mole()) / RT; + m_waterSS->setState_TP(m_tlast, m_plast); + } else { + m_g0_RT[0] = m_gss_RT[0]; + } + copy(m_g0_RT.begin(), m_g0_RT.end(), grt); + } + + void + VPSSMgr_Water_ConstVol::getGibbs_ref(doublereal *g) const{ + doublereal RT = GasConstant * m_tlast; + getGibbs_RT_ref(g); + for (int k = 0; k < m_kk; k++) { + g[k] *= RT; + } + } + + void + VPSSMgr_Water_ConstVol::getEntropy_R_ref(doublereal *sr) const{ + // Everything should be OK except for the water SS + if (m_p0 != m_plast) { + m_waterSS->setState_TP(m_tlast, m_p0); + m_s0_R[0] = (m_waterSS->entropy_mole()) / GasConstant; + m_waterSS->setState_TP(m_tlast, m_plast); + } else { + m_s0_R[0] = m_sss_R[0]; + } + copy(m_s0_R.begin(), m_s0_R.end(), sr); + } + + void + VPSSMgr_Water_ConstVol::getCp_R_ref(doublereal *cpr) const{ + // Everything should be OK except for the water SS + if (m_p0 != m_plast) { + m_waterSS->setState_TP(m_tlast, m_p0); + m_cp0_R[0] = (m_waterSS->cp_mole()) / GasConstant; + m_waterSS->setState_TP(m_tlast, m_plast); + } else { + m_cp0_R[0] = m_cpss_R[0]; + } + copy(m_cp0_R.begin(), m_cp0_R.end(), cpr); + } + + void + VPSSMgr_Water_ConstVol::getStandardVolumes_ref(doublereal *vol) const{ + // Everything should be OK except for the water SS + if (m_p0 != m_plast) { + m_waterSS->setState_TP(m_tlast, m_p0); + m_V0[0] = m_vptp_ptr->molecularWeight(0) / m_waterSS->density(); + m_waterSS->setState_TP(m_tlast, m_plast); + } else { + m_V0[0] = m_Vss[0]; + } + copy(m_V0.begin(), m_V0.end(), vol); + } + + + void VPSSMgr_Water_ConstVol::updateRefStateThermo() { + // Fix up the water + doublereal RT = GasConstant * m_tlast; + m_waterSS->setState_TP(m_tlast, m_p0); + m_h0_RT[0] = (m_waterSS->enthalpy_mole())/ RT; + m_s0_R[0] = (m_waterSS->entropy_mole()) / GasConstant; + m_cp0_R[0] = (m_waterSS->cp_mole()) / GasConstant; + m_g0_RT[0] = (m_hss_RT[0] - m_sss_R[0]); + m_V0[0] = m_vptp_ptr->molecularWeight(0) / (m_waterSS->density()); + m_waterSS->setState_TP(m_tlast, m_plast); + } + + void VPSSMgr_Water_ConstVol::_updateStandardStateThermo() { + doublereal RT = GasConstant * m_tlast; + doublereal del_pRT = (m_plast - m_p0) / (RT); + + for (int k = 1; k < m_kk; k++) { + m_hss_RT[k] = m_h0_RT[k] + del_pRT * m_Vss[k]; + m_cpss_R[k] = m_cp0_R[k]; + m_sss_R[k] = m_s0_R[k]; + m_gss_RT[k] = m_hss_RT[k] - m_sss_R[k]; + // m_Vss[k] constant + } + // Do the water + m_waterSS->setState_TP(m_tlast, m_plast); + m_hss_RT[0] = (m_waterSS->enthalpy_mole())/ RT; + m_sss_R[0] = (m_waterSS->entropy_mole()) / GasConstant; + m_cpss_R[0] = (m_waterSS->cp_mole()) / GasConstant; + m_gss_RT[0] = (m_hss_RT[0] - m_sss_R[0]); + m_Vss[0] = (m_vptp_ptr->molecularWeight(0) / m_waterSS->density()); + } + + void VPSSMgr_Water_ConstVol::initThermo() { + VPSSMgr::initThermo(); + } + + + void + VPSSMgr_Water_ConstVol::initThermoXML(XML_Node& phaseNode, std::string id) { + VPSSMgr::initThermoXML(phaseNode, id); + + XML_Node& speciesList = phaseNode.child("speciesArray"); + XML_Node* speciesDB = get_XML_NameID("speciesData", speciesList["datasrc"], + &phaseNode.root()); + const vector&sss = m_vptp_ptr->speciesNames(); + + + m_waterSS = dynamic_cast(m_vptp_ptr->providePDSS(0)); + if (!m_waterSS) { + throw CanteraError("VPSSMgr_Water_ConstVol::initThermoXML", + "bad dynamic cast"); + } + + m_waterSS->setState_TP(300., OneAtm); + m_Vss[0] = (m_waterSS->density()) / m_vptp_ptr->molecularWeight(0); + + for (int k = 1; k < m_kk; k++) { + const XML_Node* s = speciesDB->findByAttr("name", sss[k]); + if (!s) { + throw CanteraError("VPSSMgr_Water_ConstVol::initThermoXML", + "no species Node for species " + sss[k]); + } + const XML_Node *ss = s->findByName("standardState"); + if (!ss) { + throw CanteraError("VPSSMgr_Water_ConstVol::initThermoXML", + "no standardState Node for species " + s->name()); + } + std::string model = (*ss)["model"]; + if (model != "constant_incompressible") { + throw CanteraError("VPSSMgr_Water_ConstVol::initThermoXML", + "standardState model for species isn't constant_incompressible: " + s->name()); + } + m_Vss[k] = getFloat(*ss, "molarVolume", "-"); + } + } + + PDSS* + VPSSMgr_Water_ConstVol::createInstallPDSS(int k, const XML_Node& speciesNode, + const XML_Node *phaseNode_ptr) { + + PDSS *kPDSS = 0; + // Will have to do something for water + // -> make sure it's species 0 + // -> make sure it's designated as a real water EOS + if (k == 0) { + string xn = speciesNode["name"]; + if (xn != "H2O(L)") { + throw CanteraError("VPSSMgr_Water_ConstVol::installSpecies", + "h2o wrong name: " + xn); + } + const XML_Node *ss = speciesNode.findByName("standardState"); + std::string model = (*ss)["model"]; + if (model != "waterIAPWS" && model != "waterPDSS") { + throw CanteraError("VPSSMgr_Water_ConstVol::installSpecies", + "wrong SS mode: " + model); + } + if (m_waterSS) delete m_waterSS; + m_waterSS = new PDSS_Water(m_vptp_ptr, 0); + kPDSS = m_waterSS; + } else { + + VPSSMgr::installSTSpecies(k, speciesNode, phaseNode_ptr); + + const XML_Node *ss = speciesNode.findByName("standardState"); + if (!ss) { + throw CanteraError("VPSSMgr_Water_ConstVol::installSpecies", + "no standardState Node for species " + speciesNode.name()); + } + std::string model = (*ss)["model"]; + if (model != "constant_incompressible") { + throw CanteraError("VPSSMgr_Water_ConstVol::initThermoXML", + "standardState model for species isn't " + "constant_incompressible: " + speciesNode.name()); + } + if ((int) m_Vss.size() < k+1) { + m_Vss.resize(k+1, 0.0); + } + m_Vss[k] = getFloat(*ss, "molarVolume", "-"); + + // instantiate a new kPDSS object + kPDSS = new PDSS_ConstVol(m_vptp_ptr, k, speciesNode, *phaseNode_ptr, true); + } + return kPDSS; + } + + PDSS_enumType VPSSMgr_Water_ConstVol::reportPDSSType(int k) const { + return cPDSS_UNDEF; + } + + VPSSMgr_enumType VPSSMgr_Water_ConstVol::reportVPSSMgrType() const { + return cVPSSMGR_WATER_CONSTVOL; + } +} + + diff --git a/Cantera/src/thermo/VPSSMgr_Water_ConstVol.h b/Cantera/src/thermo/VPSSMgr_Water_ConstVol.h new file mode 100644 index 000000000..70400746f --- /dev/null +++ b/Cantera/src/thermo/VPSSMgr_Water_ConstVol.h @@ -0,0 +1,310 @@ +/** + * @file VPSSMgr_Water_ConstVol.h + * Declaration file for a derived class that handles the calculation + * of standard state thermo properties for real water and + * a set of species which have a constant molar volume pressure + * dependence + * (see \ref thermoprops and + * class \link Cantera::VPSSMgr_ConstVol VPSSMgr_ConstVol\endlink). + */ + +/* + * $Author$ + * $Revision$ + * $Date$ + */ +/* + * 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. + */ + +#ifndef CT_VPSSMGR_WATER_CONSTVOL_H +#define CT_VPSSMGR_WATER_CONSTVOL_H + +#include "ct_defs.h" +#include "VPSSMgr.h" + +namespace Cantera { + + class SpeciesThermoInterpType; + class VPStandardStateTP; + class SpeciesThermo; + class PDSS; + class PDSS_Water; + + //! Virtual base class for the species thermo manager classes. + /*! + * This class defines the interface which all subclasses must implement. + * + * Class %VPSSSpeciesThermo 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 VPSSMgr_Water_ConstVol : public VPSSMgr { + + public: + + //! Base Constructor + /*! + * Initialize the object. + * + * @param vp_ptr Pointer to the VPStandardStateTP standard state + * @param sp_ptr Poitner to the SpeciesThermo standard state + */ + VPSSMgr_Water_ConstVol(VPStandardStateTP *vp_ptr, SpeciesThermo *sp_ptr); + + //! Destructor + virtual ~VPSSMgr_Water_ConstVol(); + + //! Copy Constructor for the %SpeciesThermo object. + /*! + * @param right Reference to %SpeciesThermo object to be copied into the + * current one. + */ + VPSSMgr_Water_ConstVol(const VPSSMgr_Water_ConstVol &right); + + //! Assignment operator for the %SpeciesThermo object + /*! + * This is NOT a virtual function. + * + * @param right Reference to %SpeciesThermo object to be copied into the + * current one. + */ + VPSSMgr_Water_ConstVol& operator=(const VPSSMgr_Water_ConstVol &right); + + //! Duplication routine for objects which inherit from + //! %VPSSSpeciesThermo + /*! + * This virtual routine can be used to duplicate %VPSSSpeciesThermo objects + * inherited from %VPSSSpeciesThermo even if the application only has + * a pointer to %VPSSSpeciesThermo to work with. + */ + virtual VPSSMgr *duplMyselfAsVPSSMgr() const; + + /*! + * @name Properties of the Standard State of the Species in the Solution + * + * Within VPStandardStateTP, these properties are calculated via a common routine, + * _updateStandardStateThermo(), + * which must be overloaded in inherited objects. + * The values are cached within this object, and are not recalculated unless + * the temperature or pressure changes. + */ + //@{ + + + protected: + + //! Updates the standard state thermodynamic functions at the current T and P of the solution. + /*! + * @internal + * + * If m_useTmpStandardStateStorage is true, + * this function must be called for every call to functions in this + * class. It checks to see whether the temperature or pressure has changed and + * thus the ss thermodynamics functions for all of the species + * must be recalculated. + * + * This function is responsible for updating the following internal members, + * when m_useTmpStandardStateStorage is true. + * + * - m_hss_RT; + * - m_cpss_R; + * - m_gss_RT; + * - m_sss_R; + * - m_Vss + * + * If m_useTmpStandardStateStorage is not true, this function may be + * required to be called by child classes to update internal member data. + * + * Note, this will throw an error. It must be reimplemented in derived classes. + * + */ + virtual void _updateStandardStateThermo(); + + public: + + //@} + /// @name Thermodynamic Values for the Species Reference States (VPStandardStateTP) + /*! + * There are also temporary + * variables for holding the species reference-state values of Cp, H, S, and V at the + * last temperature and reference pressure called. These functions are not recalculated + * if a new call is made using the previous temperature. + * All calculations are done within the routine _updateRefStateThermo(). + */ + //@{ + /*! + * 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 contains the nondimensional enthalpies + * of the reference state of the species + * length = m_kk, units = dimensionless. + */ + 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 contains the nondimensional Gibbs free energies + * of the reference state of the species + * length = m_kk, units = dimensionless. + */ + 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 contain the Gibbs free energies + * of the reference state of the species + * 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 the species. + * + * @param er Output vector contain the nondimensional entropies + * of the species in their reference states + * length: m_kk, units: dimensionless. + */ + virtual void getEntropy_R_ref(doublereal *er) 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 the species. + * + * @param cpr Output vector contains the nondimensional heat capacities + * of the species in their reference states + * length: m_kk, units: dimensionless. + */ + virtual void getCp_R_ref(doublereal *cpr) const ; + + //! Get the molar volumes of the species reference states at the current + //! T and P_ref 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 ; + + + void updateRefStateThermo(); + + //! @name Initialization Methods - For Internal use (VPStandardState) + /*! + * The following methods are used in the process of constructing + * the phase and setting its parameters from a specification in an + * input file. They are not normally used in application programs. + * To see how they are used, see files importCTML.cpp and + * ThermoFactory.cpp. + */ + //@{ + + + //! @internal Initialize the object + /*! + * 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 + */ + + + //! Initialize the thermo, after all species have been entered. + virtual void initThermo(); + + + //! Finalize the thermo after all species have been entered + /*! + * This function is the LAST initialization routine to be + * called. It's called after createInstallPDSS() has been + * called for each species in the phase, and after initThermo() + * has been called. + * It's called via an inner-to-outer onion shell like manner. + * + * + * @param phaseNode Reference to the phaseNode XML node. + * @param id ID of the phase. + */ + virtual void initThermoXML(XML_Node& phaseNode, std::string id); + + //! Install specific content for species k in the standard-state + //! thermodynamic calculator and also create/return a PDSS object + //! for that species. + /*! + * This occurs before matrices are sized appropriately. + * + * @param k Species index in the phase + * @param speciesNode XML Node corresponding to the species + * @param phaseNode_ptr Pointer to the XML Node corresponding + * to the phase which owns the species + */ + virtual PDSS *createInstallPDSS(int k, const XML_Node& speciesNode, + const XML_Node *phaseNode_ptr); + + //! This utility function reports the type of parameterization + //! used for the species with index number index. + /*! + * + * @param index Species index + */ + virtual PDSS_enumType reportPDSSType(int index = -1) const ; + + + //! This utility function reports the type of manager + //! for the calculation of ss properties + /*! + * @return Returns an enumerated type that is unique. + */ + virtual VPSSMgr_enumType reportVPSSMgrType() const ; + + //! Initialize all internal pointers + /*! + * This is a virtual function that fills or updates the values of the + * shallow pointers. + * + * @param vp_ptr Pointer to the Variable Pressure standard state object + * @param sp_ptr Pointer to the reference state thermo calculator object + */ + virtual void initAllPtrs(VPStandardStateTP *vp_ptr, SpeciesThermo *sp_ptr); + + protected: + + + //! Pointer to the Water PDSS object. + /*! + * This is a shallow copy. The water PDSS object is owned by the VPStandardStateTP + * object. + */ + PDSS_Water *m_waterSS; + }; + //@} +} + +#endif + diff --git a/Cantera/src/thermo/VPSSMgr_Water_HKFT.cpp b/Cantera/src/thermo/VPSSMgr_Water_HKFT.cpp new file mode 100644 index 000000000..aa5a50b05 --- /dev/null +++ b/Cantera/src/thermo/VPSSMgr_Water_HKFT.cpp @@ -0,0 +1,278 @@ +/** + * @file VPSSMgr_Water_HKFT.cpp + * Definition file for a derived class that handles the calculation + * of standard state thermo properties for pure water and + * a set of species which obey the HKFT standard state + * dependence + * (see \ref thermoprops and class + * \link Cantera::VPSSMgr_Water_HKFT VPSSMgr_Water_HKFT\endlink). + */ +/* + * 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 "VPSSMgr_Water_HKFT.h" +#include "xml.h" +#include "VPStandardStateTP.h" +#include "PDSS_Water.h" + +using namespace std; + +namespace Cantera { + + VPSSMgr_Water_HKFT::VPSSMgr_Water_HKFT(VPStandardStateTP *vp_ptr, + SpeciesThermo *spth) : + VPSSMgr(vp_ptr, spth), + m_waterSS(0) + { + m_useTmpRefStateStorage = true; + m_useTmpStandardStateStorage = true; + m_waterSS = new PDSS_Water(); + } + + + VPSSMgr_Water_HKFT::~VPSSMgr_Water_HKFT() + { + delete m_waterSS; + } + + VPSSMgr_Water_HKFT::VPSSMgr_Water_HKFT(const VPSSMgr_Water_HKFT &right) : + VPSSMgr(right.m_vptp_ptr, right.m_spthermo) + { + m_useTmpRefStateStorage = true; + m_useTmpStandardStateStorage = true; + m_waterSS = new PDSS_Water(); + *this = right; + } + + + VPSSMgr_Water_HKFT& + VPSSMgr_Water_HKFT::operator=(const VPSSMgr_Water_HKFT &b) + { + if (&b == this) return *this; + VPSSMgr::operator=(b); + if (m_waterSS) delete m_waterSS; + m_waterSS = new PDSS_Water(*(b.m_waterSS)); + return *this; + } + + VPSSMgr * + VPSSMgr_Water_HKFT::duplMyselfAsVPSSMgr() const { + VPSSMgr_Water_HKFT *vpm = new VPSSMgr_Water_HKFT(*this); + return (VPSSMgr *) vpm; + } + + + void + VPSSMgr_Water_HKFT::getEnthalpy_RT_ref(doublereal *hrt) const{ + // Everything should be OK except for the water SS + if (m_p0 != m_plast) { + doublereal RT = GasConstant * m_tlast; + m_waterSS->setState_TP(m_tlast, m_p0); + m_h0_RT[0] = (m_waterSS->enthalpy_mole()) / RT; + m_waterSS->setState_TP(m_tlast, m_plast); + } else { + m_h0_RT[0] = m_hss_RT[0]; + } + copy(m_h0_RT.begin(), m_h0_RT.end(), hrt); + } + + void + VPSSMgr_Water_HKFT::getGibbs_RT_ref(doublereal *grt) const{ + // Everything should be OK except for the water SS + if (m_p0 != m_plast) { + doublereal RT = GasConstant * m_tlast; + m_waterSS->setState_TP(m_tlast, m_p0); + m_g0_RT[0] = (m_waterSS->gibbs_mole()) / RT; + m_waterSS->setState_TP(m_tlast, m_plast); + } else { + m_g0_RT[0] = m_gss_RT[0]; + } + copy(m_g0_RT.begin(), m_g0_RT.end(), grt); + } + + void + VPSSMgr_Water_HKFT::getGibbs_ref(doublereal *g) const{ + doublereal RT = GasConstant * m_tlast; + for (int k = 0; k < m_kk; k++) { + g[k] *= RT; + } + } + + void + VPSSMgr_Water_HKFT::getEntropy_R_ref(doublereal *sr) const{ + // Everything should be OK except for the water SS + if (m_p0 != m_plast) { + m_waterSS->setState_TP(m_tlast, m_p0); + m_s0_R[0] = (m_waterSS->entropy_mole()) / GasConstant; + m_waterSS->setState_TP(m_tlast, m_plast); + } else { + m_s0_R[0] = m_sss_R[0]; + } + copy(m_s0_R.begin(), m_s0_R.end(), sr); + } + + void + VPSSMgr_Water_HKFT::getCp_R_ref(doublereal *cpr) const{ + // Everything should be OK except for the water SS + if (m_p0 != m_plast) { + m_waterSS->setState_TP(m_tlast, m_p0); + m_cp0_R[0] = (m_waterSS->cp_mole()) / GasConstant; + m_waterSS->setState_TP(m_tlast, m_plast); + } else { + m_cp0_R[0] = m_cpss_R[0]; + } + copy(m_cp0_R.begin(), m_cp0_R.end(), cpr); + } + + void + VPSSMgr_Water_HKFT::getStandardVolumes_ref(doublereal *vol) const{ + // Everything should be OK except for the water SS + if (m_p0 != m_plast) { + m_waterSS->setState_TP(m_tlast, m_p0); + m_V0[0] = (m_waterSS->density()) / m_vptp_ptr->molecularWeight(0); + m_waterSS->setState_TP(m_tlast, m_plast); + } else { + m_V0[0] = m_Vss[0]; + } + copy(m_V0.begin(), m_V0.end(), vol); + } + + + void VPSSMgr_Water_HKFT::updateRefStateThermo() const { + // Fix up the water + doublereal RT = GasConstant * m_tlast; + m_waterSS->setState_TP(m_tlast, m_p0); + m_h0_RT[0] = (m_waterSS->enthalpy_mole())/ RT; + m_s0_R[0] = (m_waterSS->entropy_mole()) / GasConstant; + m_cp0_R[0] = (m_waterSS->cp_mole()) / GasConstant; + m_g0_RT[0] = (m_hss_RT[0] - m_sss_R[0]); + m_V0[0] = (m_waterSS->density()) / m_vptp_ptr->molecularWeight(0); + m_waterSS->setState_TP(m_tlast, m_plast); + } + + void VPSSMgr_Water_HKFT::_updateStandardStateThermo() { + doublereal RT = GasConstant * m_tlast; + doublereal del_pRT = (m_plast - m_p0) / (RT); + + for (int k = 1; k < m_kk; k++) { + m_hss_RT[k] = m_h0_RT[k] + del_pRT * m_Vss[k]; + m_cpss_R[k] = m_cp0_R[k]; + m_sss_R[k] = m_s0_R[k]; + m_gss_RT[k] = m_hss_RT[k] - m_sss_R[k]; + // m_Vss[k] constant + } + // Do the water + m_waterSS->setState_TP(m_tlast, m_plast); + m_hss_RT[0] = (m_waterSS->enthalpy_mole())/ RT; + m_sss_R[0] = (m_waterSS->entropy_mole()) / GasConstant; + m_cpss_R[0] = (m_waterSS->cp_mole()) / GasConstant; + m_gss_RT[0] = (m_hss_RT[0] - m_sss_R[0]); + m_Vss[0] = (m_waterSS->density()) / m_vptp_ptr->molecularWeight(0); + } + + void VPSSMgr_Water_HKFT::initThermo() { + VPSSMgr::initThermo(); + } + + + void + VPSSMgr_Water_HKFT::initThermoXML(XML_Node& phaseNode, std::string id) { + VPSSMgr::initThermoXML(phaseNode, id); + + XML_Node& speciesList = phaseNode.child("speciesArray"); + XML_Node* speciesDB = get_XML_NameID("speciesData", speciesList["datasrc"], + &phaseNode.root()); + const vector&sss = m_vptp_ptr->speciesNames(); + + if (m_waterSS) delete m_waterSS; + m_waterSS = new PDSS_Water(m_vptp_ptr, 0); + m_waterSS->setState_TP(300., OneAtm); + m_Vss[0] = (m_waterSS->density()) / m_vptp_ptr->molecularWeight(0); + + for (int k = 1; k < m_kk; k++) { + const XML_Node* s = speciesDB->findByAttr("name", sss[k]); + if (!s) { + throw CanteraError("VPSSMgr_Water_HKFT::initThermoXML", + "no species Node for species " + sss[k]); + } + const XML_Node *ss = s->findByName("standardState"); + if (!ss) { + throw CanteraError("VPSSMgr_Water_HKFT::initThermoXML", + "no standardState Node for species " + s->name()); + } + std::string model = (*ss)["model"]; + if (model != "constant_incompressible") { + throw CanteraError("VPSSMgr_Water_HKFT::initThermoXML", + "standardState model for species isn't constant_incompressible: " + s->name()); + } + m_Vss[k] = getFloat(*ss, "molarVolume", "-"); + } + } + + PDSS * + VPSSMgr_Water_HKFT::createInstallPDSS(int k, const XML_Node& speciesNode, + const XML_Node *phaseNode_ptr) { + VPSSMgr::installSTSpecies(k, speciesNode, phaseNode_ptr); + + // Will have to do something for water + // -> make sure it's species 0 + // -> make sure it's designated as a real water EOS + if (k == 0) { + string xn = speciesNode["name"]; + if (xn != "H2O(L)") { + throw CanteraError("VPSSMgr_Water_HKFT::installSpecies", + "h2o wrong name: " + xn); + } + const XML_Node *ss = speciesNode.findByName("standardState"); + std::string model = (*ss)["model"]; + if (model != "waterIAPSS" && model != "waterPDSS") { + throw CanteraError("VPSSMgr_Water_HKFT::installSpecies", + "wrong SS mode: " + model); + } + if (m_waterSS) delete m_waterSS; + m_waterSS = new PDSS_Water(m_vptp_ptr, 0); + } else { + + const XML_Node *ss = speciesNode.findByName("standardState"); + if (!ss) { + throw CanteraError("VPSSMgr_Water_HKFT::installSpecies", + "no standardState Node for species " + speciesNode.name()); + } + std::string model = (*ss)["model"]; + if (model != "constant_incompressible") { + throw CanteraError("VPSSMgr_Water_HKFT::initThermoXML", + "standardState model for species isn't " + "constant_incompressible: " + speciesNode.name()); + } + if ((int) m_Vss.size() < k+1) { + m_Vss.resize(k+1, 0.0); + } + m_Vss[k] = getFloat(*ss, "molarVolume", "-"); + } + return 0; + } + + PDSS_enumType VPSSMgr_Water_HKFT::reportPDSSType(int k) const { + return cPDSS_UNDEF; + } + + VPSSMgr_enumType VPSSMgr_Water_HKFT::reportVPSSMgrType() const { + return cVPSSMGR_WATER_HKFT; + } +} + + diff --git a/Cantera/src/thermo/VPSSMgr_Water_HKFT.h b/Cantera/src/thermo/VPSSMgr_Water_HKFT.h new file mode 100644 index 000000000..a563df566 --- /dev/null +++ b/Cantera/src/thermo/VPSSMgr_Water_HKFT.h @@ -0,0 +1,333 @@ +/** + * @file VPSSMgr_Water_HKFT.h + * Declaration file for a derived class that handles the calculation + * of standard state thermo properties for real water and + * a set of species which have the HKFT equation of state + * (see \ref thermoprops and + * class \link Cantera::VPSSMgr_Water_HKFT VPSSMgr_Water_HKFT\endlink). + */ +/* + * $Author$ + * $Revision$ + * $Date$ + */ +/* + * Copywrite (2006) Sandia Corporation. Under the terms of + * Contract DE-AC04-94AL85000 with Sandia Corporation, the + * U.S. Government retains certain rights in this software. + */ + +#ifndef CT_VPSSMGR_WATER_HKFT_H +#define CT_VPSSMGR_WATER_HKFT_H + +#include "ct_defs.h" +#include "VPSSMgr.h" + +namespace Cantera { + + class SpeciesThermoInterpType; + class VPStandardStateTP; + class SpeciesThermo; + class PDSS; + class PDSS_Water; + + //! Virtual base class for the species thermo manager classes. + /*! + * This class defines the interface which all subclasses must implement. + * + * Class %VPSSSpeciesThermo 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 VPSSMgr_Water_HKFT : public VPSSMgr { + + public: + + + //! Constructor + /*! + * @param vptp_ptr Pointer to the Variable pressure %ThermoPhase object + * This object must have already been malloced. + * + * @param spth Pointer to the optional SpeciesThermo object + * that will handle the calculation of the reference + * state thermodynamic coefficients. + */ + VPSSMgr_Water_HKFT(VPStandardStateTP *vptp_ptr, + SpeciesThermo *spth); + + //! Destructor + virtual ~VPSSMgr_Water_HKFT(); + + //! Copy Constructor for the %SpeciesThermo object. + /*! + * @param right Reference to %SpeciesThermo object to be copied into the + * current one. + */ + VPSSMgr_Water_HKFT(const VPSSMgr_Water_HKFT &right); + + //! Assignment operator for the %SpeciesThermo object + /*! + * This is NOT a virtual function. + * + * @param right Reference to %SpeciesThermo object to be copied into the + * current one. + */ + VPSSMgr_Water_HKFT& operator=(const VPSSMgr_Water_HKFT &right); + + //! Duplication routine for objects which inherit from + //! %VPSSSpeciesThermo + /*! + * This virtual routine can be used to duplicate %VPSSSpeciesThermo objects + * inherited from %VPSSSpeciesThermo even if the application only has + * a pointer to %VPSSSpeciesThermo to work with. + */ + virtual VPSSMgr *duplMyselfAsVPSSMgr() const; + + /*! + * @name Properties of the Standard State of the Species in the Solution + * + * Within VPStandardStateTP, these properties are calculated via a common routine, + * _updateStandardStateThermo(), + * which must be overloaded in inherited objects. + * The values are cached within this object, and are not recalculated unless + * the temperature or pressure changes. + */ + //@{ + + + //@} + /// @name Thermodynamic Values for the Species Reference States (VPStandardStateTP) + /*! + * There are also temporary + * variables for holding the species reference-state values of Cp, H, S, and V at the + * last temperature and reference pressure called. These functions are not recalculated + * if a new call is made using the previous temperature. + * All calculations are done within the routine _updateRefStateThermo(). + */ + //@{ + + /*! + * 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 contains the nondimensional enthalpies + * of the reference state of the species + * length = m_kk, units = dimensionless. + */ + 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 contains the nondimensional Gibbs free energies + * of the reference state of the species + * length = m_kk, units = dimensionless. + */ + 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 contain the Gibbs free energies + * of the reference state of the species + * 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 the species. + * + * @param er Output vector contain the nondimensional entropies + * of the species in their reference states + * length: m_kk, units: dimensionless. + */ + virtual void getEntropy_R_ref(doublereal *er) 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 the species. + * + * @param cpr Output vector contains the nondimensional heat capacities + * of the species in their reference states + * length: m_kk, units: dimensionless. + */ + virtual void getCp_R_ref(doublereal *cpr) const ; + + //! Get the molar volumes of the species reference states at the current + //! T and P_ref 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 Setting the Internal State of the System + /*! + * All calls to change the internal state of the system's T and P + * are done through these routines + * - setState_TP() + * - setState_T() + * - setState_P() + * + * These routine in turn call the following underlying virtual functions + * + * - _updateRefStateThermo() + * - _updateStandardStateThermo() + * + * An important point to note is that inbetween calls the assumption + * that the underlying PDSS objects will retain their set Temperatures + * and Pressure CAN NOT BE MADE. For efficiency reasons, we may twiddle + * these to get derivatives. + */ + //@{ + + //! Updates the internal reference state thermodynamic vectors at the + //! current T of the solution and the reference pressure. + /*! + * If you are to peak internally inside the object, you need to + * call these functions after setState functions in order to be sure + * that the vectors are current. + */ + virtual void updateRefStateThermo() const; + + protected: + + //! Updates the standard state thermodynamic functions at the current T and P of the solution. + /*! + * @internal + * + * If m_useTmpStandardStateStorage is true, + * this function must be called for every call to functions in this + * class. It checks to see whether the temperature or pressure has changed and + * thus the ss thermodynamics functions for all of the species + * must be recalculated. + * + * This function is responsible for updating the following internal members, + * when m_useTmpStandardStateStorage is true. + * + * - m_hss_RT; + * - m_cpss_R; + * - m_gss_RT; + * - m_sss_R; + * - m_Vss + * + * If m_useTmpStandardStateStorage is not true, this function may be + * required to be called by child classes to update internal member data. + * + * Note, this will throw an error. It must be reimplemented in derived classes. + * + */ + virtual void _updateStandardStateThermo(); + + public: + + //@} + //! @name Utility Methods - Reports on various quantities + /*! + * The following methods are used in the process of reporting + * various states and attributes + */ + //@{ + + //! This utility function reports the type of parameterization + //! used for the species with index number index. + /*! + * + * @param index Species index + */ + virtual PDSS_enumType reportPDSSType(int index = -1) const ; + + + //! This utility function reports the type of manager + //! for the calculation of ss properties + /*! + * + * + */ + virtual VPSSMgr_enumType reportVPSSMgrType() const ; + + //@} + //! @name Initialization Methods - For Internal use (VPStandardState) + /*! + * The following methods are used in the process of constructing + * the phase and setting its parameters from a specification in an + * input file. They are not normally used in application programs. + * To see how they are used, see files importCTML.cpp and + * ThermoFactory.cpp. + */ + //@{ + + //! @internal Initialize the object + /*! + * 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 + */ + virtual void initThermo(); + + //! Finalize the thermo after all species have been entered + /*! + * This function is the LAST initialization routine to be + * called. It's called after createInstallPDSS() has been + * called for each species in the phase, and after initThermo() + * has been called. + * It's called via an inner-to-outer onion shell like manner. + * + * + * @param phaseNode Reference to the phaseNode XML node. + * @param id ID of the phase. + */ + virtual void initThermoXML(XML_Node& phaseNode, std::string id); + + //! Install specific content for species k in the standard-state + //! thermodynamic calculator and also create/return a PDSS object + //! for that species. + /*! + * This occurs before matrices are sized appropriately. + * + * @param k Species index in the phase + * @param speciesNode XML Node corresponding to the species + * @param phaseNode_ptr Pointer to the XML Node corresponding + * to the phase which owns the species + */ + virtual PDSS *createInstallPDSS(int k, const XML_Node& speciesNode, + const XML_Node *phaseNode_ptr); + + //@} + + protected: + + //! Shallow pointer to the water object + PDSS_Water *m_waterSS; + }; + //@} +} + +#endif + diff --git a/Cantera/src/thermo/VPSSMgr_types.h b/Cantera/src/thermo/VPSSMgr_types.h new file mode 100644 index 000000000..4d55e1eff --- /dev/null +++ b/Cantera/src/thermo/VPSSMgr_types.h @@ -0,0 +1,70 @@ +/** + * @file VPSSMgr_types.h + * Contains const definitions for types of calculation managers + * that are responsible for calculating the species standard + * state thermodynamic managers and + * reference-state thermodynamics managers + * (see + * class \link Cantera::VPSSMgr VPSSMgr\endlink). + */ +/* + * $Author$ + * $Revision$ + * $Date$ + */ +/* + * 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. + */ + +#ifndef VPSSMGR_TYPES_H +#define VPSSMGR_TYPES_H + +//! Variable pressures SS calculator for ideal gas phases +#define VPSSMGR_IDEALGAS 1 + +//! Variable pressure SS calculate for phases consisting all +//! species having a constant molar volume property +/*! + * This fits most solids + */ +#define VPSSMGR_CONSTVOL 2 + +//! Variable pressure SS calculate for phases consisting of real water +//! as the first species and species having a constant molar volume property +#define VPSSMGR_WATER_CONSTVOL 11 + +//! Variable pressure SS calculate for phases consisting of real water +//! as the first species and species obeying the HKFT standard state +#define VPSSMGR_WATER_HKFT 12 + +//! Variable pressure SS calculate for phases consisting of completing +//! general representations +#define VPSSMGR_GENERAL 22 + +namespace Cantera { + + //! Error for unknown thermo parameterization + class UnknownVPSSMgr : public CanteraError { + public: + //! Constructor + /*! + * @param func String function id + * @param thermotype Integer specifying the thermo parameterization + * + * @todo is this used + */ + UnknownVPSSMgr(std::string func, int thermotype) { + CanteraError(func, std::string("\n ### ERROR ### \n") + + "Unknown species thermo parameterization (" + + int2str(thermotype) + ")\n\n"); + } + }; + + +} + +#endif + + diff --git a/Cantera/src/thermo/VPStandardStateTP.cpp b/Cantera/src/thermo/VPStandardStateTP.cpp index 2ac782bd6..47e641151 100644 --- a/Cantera/src/thermo/VPStandardStateTP.cpp +++ b/Cantera/src/thermo/VPStandardStateTP.cpp @@ -23,6 +23,8 @@ #endif #include "VPStandardStateTP.h" +#include "VPSSMgr.h" +#include "PDSS.h" using namespace std; @@ -34,12 +36,10 @@ namespace Cantera { VPStandardStateTP::VPStandardStateTP() : ThermoPhase(), m_Pcurrent(OneAtm), - m_tlast(-1.0), - m_tlast_ref(-1.0), - m_plast(-1.0), - m_p0(OneAtm), - m_useTmpRefStateStorage(false), - m_useTmpStandardStateStorage(false) + m_Tlast_ss(-1.0), + m_Plast_ss(-1.0), + m_P0(OneAtm), + m_VPSS_ptr(0) { } @@ -55,12 +55,10 @@ namespace Cantera { 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(false), - m_useTmpStandardStateStorage(false) + m_Tlast_ss(-1.0), + m_Plast_ss(-1.0), + m_P0(OneAtm), + m_VPSS_ptr(0) { *this = b; } @@ -71,8 +69,8 @@ namespace Cantera { * Note this stuff will not work until the underlying phase * has a working assignment operator */ - VPStandardStateTP& VPStandardStateTP:: - operator=(const VPStandardStateTP &b) { + VPStandardStateTP& + VPStandardStateTP::operator=(const VPStandardStateTP &b) { if (&b != this) { /* * Mostly, this is a passthrough to the underlying @@ -82,22 +80,36 @@ namespace Cantera { /* * 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; + m_Pcurrent = b.m_Pcurrent; + m_Tlast_ss = b.m_Tlast_ss; + m_Plast_ss = b.m_Plast_ss; + m_P0 = b.m_P0; + + + + // copy the pdss objects + if (m_PDSS_storage.size() > 0) { + for (int k = 0; k < (int) m_PDSS_storage.size(); k++) { + delete(m_PDSS_storage[k]); + } + } + m_PDSS_storage.resize(m_kk); + for (int k = 0; k < m_kk; k++) { + PDSS *ptmp = b.m_PDSS_storage[k]; + m_PDSS_storage[k] = ptmp->duplMyselfAsPDSS(); + } + + if (m_VPSS_ptr) { + delete m_VPSS_ptr; + m_VPSS_ptr = 0; + } + m_VPSS_ptr = (b.m_VPSS_ptr)->duplMyselfAsVPSSMgr(); + m_VPSS_ptr->initAllPtrs(this, m_spthermo); + + for (int k = 0; k < m_kk; k++) { + PDSS *ptmp = b.m_PDSS_storage[k]; + ptmp->initAllPtrs(this, m_VPSS_ptr, m_spthermo); + } } return *this; } @@ -105,10 +117,12 @@ namespace Cantera { /* * ~VPStandardStateTP(): (virtual) * - * This destructor does nothing. All of the owned objects - * handle themselves. */ VPStandardStateTP::~VPStandardStateTP() { + for (int k = 0; k < (int) m_PDSS_storage.size(); k++) { + delete(m_PDSS_storage[k]); + } + delete m_VPSS_ptr; } /* @@ -119,8 +133,24 @@ namespace Cantera { VPStandardStateTP* vptp = new VPStandardStateTP(*this); return (ThermoPhase *) vptp; } - - + + // This method returns the convention used in specification + // of the standard state, of which there are currently two, + // temperature based, and variable pressure based. + /* + * Currently, there are two standard state conventions: + * - Temperature-based activities + * cSS_CONVENTION_TEMPERATURE 0 + * - default + * + * - Variable Pressure and Temperature -based activities + * cSS_CONVENTION_VPSS 1 + */ + int VPStandardStateTP::standardStateConvention() const { + return cSS_CONVENTION_VPSS; + } + + /* * ------------Molar Thermodynamic Properties ------------------------- */ @@ -164,77 +194,42 @@ namespace Cantera { } } + inline 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(); - } + updateStandardStateThermo(); + m_VPSS_ptr->getEnthalpy_RT(hrt); } 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(); - } + updateStandardStateThermo(); + m_VPSS_ptr->getEntropy_R(srt); } + inline 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(); - } + updateStandardStateThermo(); + m_VPSS_ptr->getGibbs_RT(grt); } + inline void VPStandardStateTP::getPureGibbs(doublereal* g) const { - getGibbs_RT(g); - doublereal RT = _RT(); - for (int k = 0; k < m_kk; k++) { - g[k] *= RT; - } + updateStandardStateThermo(); + m_VPSS_ptr->getStandardChemPotentials(g); } 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(); - } + updateStandardStateThermo(); + m_VPSS_ptr->getIntEnergy_RT(urt); } 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(); - } + updateStandardStateThermo(); + m_VPSS_ptr->getCp_R(cpr); } 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(); - } + updateStandardStateThermo(); + m_VPSS_ptr->getStandardVolumes(vol); } /* @@ -247,23 +242,8 @@ namespace Cantera { * 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"); - } + updateStandardStateThermo(); + m_VPSS_ptr->getEnthalpy_RT_ref(hrt); } /* @@ -272,24 +252,9 @@ namespace Cantera { * 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"); - } - } + updateStandardStateThermo(); + m_VPSS_ptr->getGibbs_RT_ref(grt); + } /* * Returns the vector of the @@ -301,11 +266,13 @@ namespace Cantera { * 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; - } + updateStandardStateThermo(); + m_VPSS_ptr->getGibbs_ref(g); + } + + const vector_fp & VPStandardStateTP::Gibbs_RT_ref() const { + updateStandardStateThermo(); + return m_VPSS_ptr->Gibbs_RT_ref(); } /* @@ -314,23 +281,8 @@ namespace Cantera { * 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"); - } + updateStandardStateThermo(); + m_VPSS_ptr->getEntropy_R_ref(er); } /* @@ -340,23 +292,8 @@ namespace Cantera { * 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"); - } + updateStandardStateThermo(); + m_VPSS_ptr->getCp_R_ref(cpr); } /* @@ -365,14 +302,10 @@ namespace Cantera { * * 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"); - } - } + void VPStandardStateTP::getStandardVolumes_ref(doublereal *vol) const { + updateStandardStateThermo(); + m_VPSS_ptr->getStandardVolumes_ref(vol); + } /* * Perform initializations after all species have been @@ -381,34 +314,81 @@ namespace Cantera { void VPStandardStateTP::initThermo() { initLengths(); ThermoPhase::initThermo(); + m_VPSS_ptr->initThermo(); + for (int k = 0; k < m_kk; k++) { + PDSS *kPDSS = m_PDSS_storage[k]; + if (kPDSS) { + kPDSS->initThermo(); + } + } } + void VPStandardStateTP::setVPSSMgr(VPSSMgr *vp_ptr) { + m_VPSS_ptr = vp_ptr; + } + /* * Initialize the internal lengths. * (this is not a virtual function) */ void VPStandardStateTP::initLengths() { m_kk = nSpecies(); - int leng = m_kk; + + } + + + void VPStandardStateTP::setTemperature(doublereal t) { + State::setTemperature(t); + //updateStandardStateThermo(); + } + + + void VPStandardStateTP::setState_TP(doublereal t, doublereal pres) { /* - * malloc the storage for this even if - * m_useTmpRefStateStorage is set to false. - * So many functions need that temporary storage anyway. - * However, that variable is still used to see if the - * storage is used to supply the complete picture. + * A pretty tricky algorithm is needed here, due to problems involving + * standard states of real fluids. For those cases you need + * to combine the T and P specification for the standard state, or else + * you may venture into the forbidden zone, especially when nearing the + * triple point. + * Therefore, we need to do the standard state thermo calc with the + * (t, pres) combo. */ - 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); + State::setTemperature(t); + m_Pcurrent = pres; + updateStandardStateThermo(); + /* + * Now, we still need to do the calculations for general ThermoPhase objects. + * So, we switch back to a virtual function call, setTemperature, and + * setPressure to recalculate stuff at the higher level. At this point, + * we haven't touched m_tlast or m_plast, so some calculations may still + * need to be done at the ThermoPhase object level. + */ + setTemperature(t); + setPressure(pres); + } + + + + void + VPStandardStateTP::createInstallPDSS(int k, const XML_Node& s, + const XML_Node * phaseNode_ptr) { + if ((int) m_PDSS_storage.size() < k+1) { + m_PDSS_storage.resize(k+1,0); } + if (m_PDSS_storage[k] != 0) { + delete m_PDSS_storage[k] ; + } + m_PDSS_storage[k] = m_VPSS_ptr->createInstallPDSS(k, s, phaseNode_ptr); + } + + PDSS * + VPStandardStateTP::providePDSS(int k) { + return m_PDSS_storage[k]; + } + + const PDSS * + VPStandardStateTP::providePDSS(int k) const { + return m_PDSS_storage[k]; } /* @@ -430,44 +410,23 @@ namespace Cantera { */ 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]; - } + + m_VPSS_ptr->initThermo(); + for (int k = 0; k < m_kk; k++) { + PDSS *kPDSS = m_PDSS_storage[k]; + if (kPDSS) { + kPDSS->initThermo(); } } + m_VPSS_ptr->initThermoXML(phaseNode, id); + ThermoPhase::initThermoXML(phaseNode, id); } - + + + VPSSMgr *VPStandardStateTP::provideVPSSMgr() { + return m_VPSS_ptr; + } + /* * void _updateStandardStateThermo() (protected, virtual, const) * @@ -482,22 +441,17 @@ namespace Cantera { * * 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; + void VPStandardStateTP::_updateStandardStateThermo() const { + double Tnow = temperature(); + m_Plast_ss = m_Pcurrent; + m_Tlast_ss = Tnow; + m_VPSS_ptr->setState_TP(Tnow, m_Pcurrent); + } + + void VPStandardStateTP::updateStandardStateThermo() const { + double Tnow = temperature(); + if (Tnow != m_Tlast_ss || m_Pcurrent != m_Plast_ss) { + _updateStandardStateThermo(); } } } diff --git a/Cantera/src/thermo/VPStandardStateTP.h b/Cantera/src/thermo/VPStandardStateTP.h index 951682f04..95204725c 100644 --- a/Cantera/src/thermo/VPStandardStateTP.h +++ b/Cantera/src/thermo/VPStandardStateTP.h @@ -23,10 +23,12 @@ #define CT_VPSTANDARDSTATETP_H #include "ThermoPhase.h" +#include "VPSSMgr.h" namespace Cantera { class XML_Node; + class PDSS; /** * @ingroup thermoprops @@ -39,53 +41,18 @@ namespace Cantera { * variables for holding the species standard state values * of Cp, H, S, G, and V at the * last temperature and pressure called. These functions are not recalculated - * if a new call is made using the previous temperature and pressure. - * - * There are also temporary - * variables for holding the species reference-state values of Cp, H, S, and G at the - * last temperature and reference pressure called. These functions are not recalculated - * if a new call is made using the previous temperature. + * if a new call is made using the previous temperature and pressure. Currently, + * these variables and the calculation method are handled by the VPSSMgr class, + * for which VPStandardStateTP owns a pointer to. * * To support the above functionality, pressure and temperature variables, - * m_plast and m_tlast, are kept which store the last pressure and temperature - * used in the evaluation of standard state properties. An optional utility is provided - * to store the results from the last temperature and pressure standard - * state calculation and use it on subsequent calculations, if the temperature - * and pressure are unchanged. - * - * If #m_useTmpRefStateStorage is set to true, then the following internal - * arrays, containing information about the reference arrays, - * are calculated and kept up to date at every call. - * - * - #m_h0_RT - * - #m_g0_RT - * - #m_s0_R - * - #m_cp0_R - * - * The virtual function #_updateRefStateThermo() is supplied to do this - * and may be reimplemented in child routines. A default implementation - * based on the speciesThermo class is supplied in this base class. - * #_updateStandardStateThermo() is called whenever a reference state - * property is needed. - * - * When #m_useTmpStandardStateStorage is true, then the following - * internal arrays, containing information on the standard state properties - * are calculated and kept up to date. - * - * - #m_hss_RT; - * - #m_cpss_R; - * - #m_gss_RT; - * - #m_sss_R; - * - #m_Vss - * - * The virtual function #_updateStandardStateThermo() is supplied to do this - * and must be reimplemented in child routines, when #m_useTmpStandardStateStorage is true. - * It may be optionally reimplemented in child routines if - * #m_useTmpStandardStateStorage is false. - * #_updateStandardStateThermo() is called whenever a standard state property is needed. + * m_plast_ss and m_tlast_ss, are kept which store the last pressure and temperature + * used in the evaluation of standard state properties. * * This class is usually used for nearly incompressible phases. For those phases, it - * makes sense to change the equation of state independent variable from density to pressure. + * makes sense to change the equation of state independent variable from + * density to pressure. The variable m_Pcurrent contains the current value of the + * pressure within the phase. * * @todo * Put some teeth into this level by overloading the setDensity() function. It should @@ -134,6 +101,20 @@ namespace Cantera { */ virtual int eosType() const { return 0; } + //! This method returns the convention used in specification + //! of the standard state, of which there are currently two, + //! temperature based, and variable pressure based. + /*! + * Currently, there are two standard state conventions: + * - Temperature-based activities + * cSS_CONVENTION_TEMPERATURE 0 + * - default + * + * - Variable Pressure and Temperature -based activities + * cSS_CONVENTION_VPSS 1 + */ + virtual int standardStateConvention() const; + //@} @@ -266,13 +247,69 @@ namespace Cantera { */ virtual void getStandardVolumes(doublereal *vol) const; - + + //! Set the temperature of the phase + /*! + * Currently this just passes down to State::setTemperature() + * without doing anything. Calculations are changing temperatures are triggered + * later. + * + * @param T Temperature (kelvin) + */ + virtual void setTemperature(doublereal T); + + + //! Set the temperature and pressure at the same time + /*! + * Note this function currently triggers a reevalulation of the standard + * state quantities. + * + * @param T temperature (kelvin) + * @param pres pressure (pascal) + */ + virtual void setState_TP(doublereal T, doublereal pres); + + //! Returns the current pressure of the phase + /*! + * The pressure is an independent variable in this phase. Its current value + * is storred in the object VPStandardStateTP. + * + * @return return the pressure in pascals. + */ + doublereal pressure() const { + return m_Pcurrent; + } protected: //! Updates the standard state thermodynamic functions at the current T and P of the solution. /*! * @internal + * + * If m_useTmpStandardStateStorage is true, + * this function must be called for every call to functions in this class. + * + * This function is responsible for updating the following internal members, + * when m_useTmpStandardStateStorage is true. + * + * - m_hss_RT; + * - m_cpss_R; + * - m_gss_RT; + * - m_sss_R; + * - m_Vss + * + * This function doesn't check to see if the temperature or pressure + * has changed. It automatically assumes that it has changed. + * If m_useTmpStandardStateStorage is not true, this function may be + * required to be called by child classes to update internal member data.. + * + */ + virtual void _updateStandardStateThermo() const; + + public: + + //! Updates the standard state thermodynamic functions at the current T and P of the solution. + /*! * * If m_useTmpStandardStateStorage is true, * this function must be called for every call to functions in this @@ -292,14 +329,8 @@ namespace Cantera { * If m_useTmpStandardStateStorage is not true, this function may be * required to be called by child classes to update internal member data. * - * Note, this will throw an error. It must be reimplemented in derived classes. - * - * @param pres Pressure at which to carry out the calculation. - * The default is to use the current pressure, storred in m_Pcurrent. - */ - virtual void _updateStandardStateThermo(doublereal pres = -1.0) const; - - public: + */ + virtual void updateStandardStateThermo() const; //@} /// @name Thermodynamic Values for the Species Reference States (VPStandardStateTP) @@ -312,11 +343,11 @@ namespace Cantera { */ //@{ + + //! Returns the vector of nondimensional + //! enthalpies of the reference state at the current temperature + //! of the solution and the reference pressure for the species. /*! - * 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 contains the nondimensional enthalpies * of the reference state of the species * length = m_kk, units = dimensionless. @@ -333,7 +364,10 @@ namespace Cantera { * length = m_kk, units = dimensionless. */ virtual void getGibbs_RT_ref(doublereal *grt) const; - + + protected: + const vector_fp & Gibbs_RT_ref() const; + public: /*! * Returns the vector of the * gibbs function of the reference state at the current temperature @@ -381,28 +415,7 @@ namespace Cantera { protected: - //! Recalculate the Reference state thermo functions - /*! - * 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. - */ - virtual void _updateRefStateThermo() const; - + //@} @@ -441,8 +454,11 @@ namespace Cantera { * 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(). + * description, this method is called after calling installSpecies() + * for each species in the phase. It's called before calling + * initThermoXML() for the phase. Therefore, it's the correct + * place for initializing vectors which have lengths equal to the + * number of species. * * @see importCTML.cpp */ @@ -451,7 +467,6 @@ namespace Cantera { //! Initialize a ThermoPhase object, potentially reading activity //! coefficient information from an XML database. /*! - * * This routine initializes the lengths in the current object and * then calls the parent routine. * This method is provided to allow @@ -477,6 +492,24 @@ namespace Cantera { */ virtual void initThermoXML(XML_Node& phaseNode, std::string id); + + //! set the VPSS Mgr + /*! + * @param vp_ptr Pointer to the manager + */ + void setVPSSMgr(VPSSMgr *vp_ptr); + + //! Return a pointer to the VPSSMgr for this phase + /*! + * @return Returns a pointer to the VPSSMgr for this phase + */ + VPSSMgr *provideVPSSMgr(); + + void createInstallPDSS(int k, const XML_Node& s, const XML_Node * phaseNode_ptr); + + PDSS* providePDSS(int k); + const PDSS* providePDSS(int k) const; + private: //! @internal Initialize the internal lengths in this object. /*! @@ -488,92 +521,36 @@ namespace Cantera { protected: - //! The current pressure of the solution (Pa) - /*! - * It gets initialized to 1 atm. - */ - mutable doublereal m_Pcurrent; - - //! The last temperature at which the reference thermodynamic properties were calculated at. - mutable doublereal m_tlast; + //! Current value of the pressure + doublereal m_Pcurrent; - //! The last temperature at which the reference thermodynamic properties were calculated at. - mutable doublereal m_tlast_ref; + //! The last temperature at which the standard statethermodynamic properties were calculated at. + mutable doublereal m_Tlast_ss; - //! The last pressure at which the Standard State thermodynamic properties were calculated at. - mutable doublereal m_plast; + //! The last pressure at which the Standard State thermodynamic + //! properties were calculated at. + mutable doublereal m_Plast_ss; /*! * Reference pressure (Pa) must be the same for all species * - defaults to 1 atm. */ - doublereal m_p0; + doublereal m_P0; + // -> suggest making this private! + protected: + + //! Pointer to the VPSS manager that calculates all of the standard state + //! info efficiently. + mutable VPSSMgr *m_VPSS_ptr; + + //! Storage for the PDSS objects for the species /*! - * boolean indicating whether temporary reference state storage is used - * -> default is false + * Storage is in species index order. + * VPStandardStateTp owns each of the objects. + * Copy operations are deep. */ - bool m_useTmpRefStateStorage; - - /*! - * Vector containing the species reference enthalpies at T = m_tlast - * and P = p_ref. - */ - mutable vector_fp m_h0_RT; - - /** - * Vector containing the species reference constant pressure - * heat capacities at T = m_tlast and P = p_ref. - */ - mutable vector_fp m_cp0_R; - - /** - * Vector containing the species reference Gibbs functions - * at T = m_tlast and P = p_ref. - */ - mutable vector_fp m_g0_RT; - - /** - * Vector containing the species reference entropies - * at T = m_tlast and P = p_ref. - */ - mutable vector_fp m_s0_R; - - /*! - * boolean indicating whether temporary standard state storage is used - * -> default is false - */ - bool m_useTmpStandardStateStorage; - - /** - * Vector containing the species Standard State enthalpies at T = m_tlast - * and P = m_plast. - */ - mutable vector_fp m_hss_RT; - - /** - * Vector containing the species Standard State constant pressure - * heat capacities at T = m_tlast and P = m_plast. - */ - mutable vector_fp m_cpss_R; - - /** - * Vector containing the species Standard State Gibbs functions - * at T = m_tlast and P = m_plast. - */ - mutable vector_fp m_gss_RT; - - /** - * Vector containing the species Standard State entropies - * at T = m_tlast and P = m_plast. - */ - mutable vector_fp m_sss_R; - - /** - * Vector containing the species standard state volumes - * at T = m_tlast and P = m_plast - */ - mutable vector_fp m_Vss; + std::vector m_PDSS_storage; private: @@ -588,9 +565,3 @@ namespace Cantera { } #endif - - - - - - diff --git a/Cantera/src/thermo/WaterProps.cpp b/Cantera/src/thermo/WaterProps.cpp index 1dc91919b..65c8b7627 100644 --- a/Cantera/src/thermo/WaterProps.cpp +++ b/Cantera/src/thermo/WaterProps.cpp @@ -18,7 +18,7 @@ #include "WaterProps.h" #include "ctml.h" -#include "WaterPDSS.h" +#include "PDSS_Water.h" #include "WaterPropsIAPWS.h" #include @@ -40,7 +40,7 @@ namespace Cantera { * constructor -> object in slave mode, It doesn't own its * own water evaluator. */ - WaterProps::WaterProps(WaterPDSS *wptr) : + WaterProps::WaterProps(PDSS_Water *wptr) : m_waterIAPWS(0), m_own_sub(false) { diff --git a/Cantera/src/thermo/WaterProps.h b/Cantera/src/thermo/WaterProps.h index f486ba8d6..0da02f97e 100644 --- a/Cantera/src/thermo/WaterProps.h +++ b/Cantera/src/thermo/WaterProps.h @@ -21,15 +21,74 @@ #include "ct_defs.h" class WaterPropsIAPWS; namespace Cantera { - class WaterPDSS; + class PDSS_Water; /** * @defgroup relatedProps Electric Properties of Phases * * - * These classes are used to compute the electrical and electrothermochemical properties of + *

+ * Treatment of the %Phase Potential and the electrochemical potential of a species + *

+ * + * + * The electrochemical potential of species k in a phase p, \f$ \zeta_k \f$, + * is related to the chemical potential via + * the following equation, + * + * \f[ + * \zeta_{k}(T,P) = \mu_{k}(T,P) + z_k \phi_p + * \f] + * + * where \f$ \nu_k \f$ is the charge of species k, and \f$ \phi_p \f$ is + * the electric potential of phase p. + * + * The potential \f$ \phi_p \f$ is tracked and internally storred within + * the base %ThermoPhase object. It constitutes a specification of the + * internal state of the phase; it's the third state variable, the first + * two being temperature and density (or, pressure, for incompressible + * equations of state). It may be set with the function, + * ThermoPhase::setElectricPotential(), + * and may be queried with the function ThermoPhase::electricPotential(). + * + * Note, the overall electrochemical potential of a phase may not be + * changed by the potential because many phases enforce charge + * neutrality: + * + * \f[ + * 0 = \sum_k z_k X_k + * \f] + * + * Whether charge neutrality is necessary for a phase is also specified + * within the ThermoPhase object, by the function call + * ThermoPhase::chargeNeutralityNecessary(). Note, that it is not + * necessary for the IdealGas phase, currently. However, it is + * necessary for liquid phases such as Cantera::DebyeHuckel and + * Cantera::HMWSoln for the proper specification of the chemical potentials. + * + * + * This equation, when applied to the \f$ \zeta_k \f$ equation described + * above, results in a zero net change in the effective Gibbs free + * energy of the phase. However, specific charged species in the phase + * may increase or decrease their electochemical potentials, which will + * have an effect on interfacial reactions involving charged species, + * when there is a potential drop between phases. This effect is used + * within the Cantera::InterfaceKinetics and Cantera::EdgeKinetics kinetics + * objects classes. + * + * + *

+ * Electrothermochemical Properties of Phases of Matter. + *

+ * + * The following classes are used to compute the electrical and electrothermochemical properties of * phases of matter. The main property currently is the dielectric * constant, which is an important parameter for electolyte solutions. + * The class WaterProps calculate the dielectric constant of water as a function of + * temperature and pressure. + * + * WaterProps also calculate the constant A_debye used in the Debye Huckel + * and Pitzer activity coefficient calculations. * * * @ingroup phases @@ -60,7 +119,7 @@ namespace Cantera { /*! * @param wptr Pointer to water standard state object */ - WaterProps(WaterPDSS *wptr); + WaterProps(PDSS_Water *wptr); //! Copy Constructor /*! diff --git a/Cantera/src/thermo/mix_defs.h b/Cantera/src/thermo/mix_defs.h index d22596f2a..bf5e7abd5 100755 --- a/Cantera/src/thermo/mix_defs.h +++ b/Cantera/src/thermo/mix_defs.h @@ -3,74 +3,110 @@ 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; + /** + * 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; - const int cHarmonicOsc = 4; + // species thermo types + const int cNASA = 1; + const int cShomate = 2; + const int cNASA96 = 3; + const int cHarmonicOsc = 4; - /** - * 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; + /** + * 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 cSemiconductor = 7; + /// 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 cSemiconductor = 7; - const int cLatticeSolid = 20; // LatticeSolidPhase.h - const int cLattice = 21; + const int cLatticeSolid = 20; // LatticeSolidPhase.h + const int cLattice = 21; - // pure fluids with liquid/vapor eqs of state - const int cPureFluid = 10; + // pure fluids with liquid/vapor eqs of state + const int cPureFluid = 10; - /// An edge between two 2D surfaces - const int cEdge = 6; + /// An edge between two 2D surfaces + const int cEdge = 6; - /// Constant partial molar volume solution IdealSolidSolnPhase.h - const int cIdealSolidSolnPhase = 5009; + /// Constant partial molar volume solution IdealSolidSolnPhase.h + const int cIdealSolidSolnPhase = 5009; - //! HMW - Strong electrolyte using the Pitzer formulation - const int cHMW = 40; + //! HMW - Strong electrolyte using the Pitzer formulation + const int cHMW = 40; - //! DebyeHuckel - Weak electrolyte using various Debye-Huckel formulations - const int cDebyeHuckel = 50; + //! DebyeHuckel - Weak electrolyte using various Debye-Huckel formulations + const int cDebyeHuckel = 50; - //! IdealMolalSoln - molality based solution with molality-based act coeffs of 1 - const int cIdealMolalSoln = 60; + //! IdealMolalSoln - molality based solution with molality-based act coeffs of 1 + const int cIdealMolalSoln = 60; - // 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; + const int cIdealSolnGasVPSS = 500; + const int cIdealSolnGasVPSS_iscv = 501; + + + + //! Variable Pressure Standard State ThermoPhase objects + const int cVPSS_IdealGas = 1001; + const int cVPSS_ConstVol = 1002; + const int cVPSS_PureFluid = 1010; + const int cVPSS_HMW = 1040; + const int cVPSS_DebyeHuckel = 1050; + const int cVPSS_MolalSoln = 1060; + + //! Types of PDSS's + enum PDSS_enumType { + cPDSS_UNDEF = 100, + cPDSS_IDEALGAS, + cPDSS_CONSTVOL, + cPDSS_MOLAL_CONSTVOL, + cPDSS_WATER, + cPDSS_MOLAL_HKFT + }; + + + //! enum for VPSSMgr types + enum VPSSMgr_enumType { + cVPSSMGR_UNDEF = 1000, + cVPSSMGR_IDEALGAS, + cVPSSMGR_CONSTVOL , + cVPSSMGR_PUREFLUID, + cVPSSMGR_WATER_CONSTVOL, + cVPSSMGR_WATER_HKFT, + cVPSSMGR_GENERAL + }; + + + // 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