From e46b6f2b2d6b1c653ba759776c7f1e8e4faaa7a3 Mon Sep 17 00:00:00 2001 From: Harry Moffat Date: Sat, 23 Aug 2008 00:53:54 +0000 Subject: [PATCH] PDSS refactor - Addition of VPSSMgr Basically, this makes the specification of standard states and the specification of activities independent of each other. PDSS Behavior ------------------------- PDSS is an object that carries out and reports on the evaluation of the pressure dependent standard state of a single species in a mixture. VPSSMgr Point of View -------------------------------------- This is the calculator for the standard states. From The Point of View of the ThermoPhase Function --------------------------------------------------------- At the VPStandardStateTP object, the ThermoPhase object is enriched to include a new object called VPSSMgr. VPSSMgr is a base class that is responsible for calculating the standard states of all of the species in the mixture. It is analogous to the SpeciesThermo virtual base class, which handles all of the reference state calculations for a class. The VPSSMgr class usurps all calculations. There are PDSS objects for each species. VPStandardStateTP contains a vector of pointers to PDSS, of length nSpecies in the phase. It owns the list. VPSSMgr also contains the same vector of pointers to PDSS, of length nSpecies in the phase. VPSSMgr is a methods class. It organizes how to calculate the SS values efficiently. It may also have specific rules for how to handle the pressure dependence (i.e., there will be a specific class for ideal gases). The VPSSMgr organizes when to update the internal states of the PDSS objects. The determination of which VPSSMgr virtual class to use with which phase is determined by the phase itself. It know which method to use. setState Treatment with Temperature and Pressure ------------------------------------------------------ The VPStandardStateTP object always has the current value of T and P held within it. It determines when T and P have changed. If it determines that T or P has changed, it calls VPSSMgr so that VPSSMgr may update its internal states. VPSSMgr contains the current T and P, also, separately. If it determines that T or P has changed, it recalculates its own internal state. PDSS Object point of View ----------------------------------------- During the evaluation of the phase thermodynamics, the PDSS object may be called to evaluate the (T,P) Standard State and RefState information. The PDSS object may or may not own the reference state calculation. If it doesn't own the calculation, the ThermoPhase object owns the calculation through its m_spthermo object. Then the PDSS objects uses pointers into the m_spthermo object to satisfy its requirement to supply (T,P) ss information. It may own or surplant the reference state calculation. For example, for waterPDSS, there is no specific reference state calculation, since the regular temperature polynomial process is ignored (except to set the basis state). The reference state functions are evaluated the same as other standard state functions. If PDSS owns the calculation of the reference state thermo, then the m_spthermo pointer within the PDSS object is zero. It does it's own reference state calculation. If PDSS uses the SpeciesThermo object to calculate the reference state, it needs to know whether the SpeciesThermo object calculations are current. It checks this. If it is, then it retrieves the result from storage in VPSSMgr object. If it isn't, then it recalculates the results. PDSS has its own storage for the current state of T and P. --- Cantera/src/thermo/DebyeHuckel.cpp | 351 +------ Cantera/src/thermo/DebyeHuckel.h | 194 +--- Cantera/src/thermo/GeneralSpeciesThermo.cpp | 189 ++-- Cantera/src/thermo/GeneralSpeciesThermo.h | 6 +- Cantera/src/thermo/HMWSoln.cpp | 366 +------ Cantera/src/thermo/HMWSoln.h | 208 +--- Cantera/src/thermo/HMWSoln_input.cpp | 22 +- Cantera/src/thermo/IdealGasPDSS.cpp | 379 -------- Cantera/src/thermo/IdealGasPDSS.h | 164 ---- Cantera/src/thermo/IdealGasPhase.cpp | 32 +- Cantera/src/thermo/IdealMolalSoln.cpp | 201 +--- Cantera/src/thermo/IdealMolalSoln.h | 147 +-- Cantera/src/thermo/IdealSolidSolnPhase.h | 1 - Cantera/src/thermo/IdealSolnGasVPSS.cpp | 530 ++++++++++ Cantera/src/thermo/IdealSolnGasVPSS.h | 452 +++++++++ Cantera/src/thermo/Makefile.in | 24 +- Cantera/src/thermo/MolalityVPSSTP.cpp | 9 +- Cantera/src/thermo/MolalityVPSSTP.h | 1 + Cantera/src/thermo/PDSS.cpp | 407 ++++---- Cantera/src/thermo/PDSS.h | 457 +++++++-- Cantera/src/thermo/PDSSFactory.cpp | 46 + Cantera/src/thermo/PDSS_ConstVol.cpp | 350 +++++++ Cantera/src/thermo/PDSS_ConstVol.h | 408 ++++++++ Cantera/src/thermo/PDSS_HKFT.cpp | 301 ++++++ Cantera/src/thermo/PDSS_HKFT.h | 416 ++++++++ Cantera/src/thermo/PDSS_IdealGas.cpp | 344 +++++++ Cantera/src/thermo/PDSS_IdealGas.h | 427 ++++++++ Cantera/src/thermo/PDSS_Water.cpp | 472 +++++++++ Cantera/src/thermo/PDSS_Water.h | 498 ++++++++++ Cantera/src/thermo/SpeciesThermo.h | 40 +- Cantera/src/thermo/SpeciesThermoFactory.cpp | 37 +- Cantera/src/thermo/SpeciesThermoFactory.h | 48 +- Cantera/src/thermo/State.h | 8 +- Cantera/src/thermo/ThermoFactory.cpp | 80 +- Cantera/src/thermo/ThermoFactory.h | 10 +- Cantera/src/thermo/ThermoPhase.cpp | 22 +- Cantera/src/thermo/ThermoPhase.h | 554 ++++++++++- Cantera/src/thermo/VPSSMgr.cpp | 423 ++++++++ Cantera/src/thermo/VPSSMgr.h | 914 ++++++++++++++++++ Cantera/src/thermo/VPSSMgrFactory.cpp | 349 +++++++ Cantera/src/thermo/VPSSMgrFactory.h | 276 ++++++ Cantera/src/thermo/VPSSMgr_ConstVol.cpp | 164 ++++ Cantera/src/thermo/VPSSMgr_ConstVol.h | 207 ++++ Cantera/src/thermo/VPSSMgr_General.cpp | 168 ++++ Cantera/src/thermo/VPSSMgr_General.h | 224 +++++ Cantera/src/thermo/VPSSMgr_IdealGas.cpp | 140 +++ Cantera/src/thermo/VPSSMgr_IdealGas.h | 229 +++++ Cantera/src/thermo/VPSSMgr_Water_ConstVol.cpp | 298 ++++++ Cantera/src/thermo/VPSSMgr_Water_ConstVol.h | 310 ++++++ Cantera/src/thermo/VPSSMgr_Water_HKFT.cpp | 278 ++++++ Cantera/src/thermo/VPSSMgr_Water_HKFT.h | 333 +++++++ Cantera/src/thermo/VPSSMgr_types.h | 70 ++ Cantera/src/thermo/VPStandardStateTP.cpp | 426 ++++---- Cantera/src/thermo/VPStandardStateTP.h | 299 +++--- Cantera/src/thermo/WaterProps.cpp | 4 +- Cantera/src/thermo/WaterProps.h | 65 +- Cantera/src/thermo/mix_defs.h | 150 +-- 57 files changed, 10586 insertions(+), 2942 deletions(-) delete mode 100644 Cantera/src/thermo/IdealGasPDSS.cpp delete mode 100644 Cantera/src/thermo/IdealGasPDSS.h create mode 100644 Cantera/src/thermo/IdealSolnGasVPSS.cpp create mode 100644 Cantera/src/thermo/IdealSolnGasVPSS.h create mode 100644 Cantera/src/thermo/PDSSFactory.cpp create mode 100644 Cantera/src/thermo/PDSS_ConstVol.cpp create mode 100644 Cantera/src/thermo/PDSS_ConstVol.h create mode 100644 Cantera/src/thermo/PDSS_HKFT.cpp create mode 100644 Cantera/src/thermo/PDSS_HKFT.h create mode 100644 Cantera/src/thermo/PDSS_IdealGas.cpp create mode 100644 Cantera/src/thermo/PDSS_IdealGas.h create mode 100644 Cantera/src/thermo/PDSS_Water.cpp create mode 100644 Cantera/src/thermo/PDSS_Water.h create mode 100644 Cantera/src/thermo/VPSSMgr.cpp create mode 100644 Cantera/src/thermo/VPSSMgr.h create mode 100644 Cantera/src/thermo/VPSSMgrFactory.cpp create mode 100644 Cantera/src/thermo/VPSSMgrFactory.h create mode 100644 Cantera/src/thermo/VPSSMgr_ConstVol.cpp create mode 100644 Cantera/src/thermo/VPSSMgr_ConstVol.h create mode 100644 Cantera/src/thermo/VPSSMgr_General.cpp create mode 100644 Cantera/src/thermo/VPSSMgr_General.h create mode 100644 Cantera/src/thermo/VPSSMgr_IdealGas.cpp create mode 100644 Cantera/src/thermo/VPSSMgr_IdealGas.h create mode 100644 Cantera/src/thermo/VPSSMgr_Water_ConstVol.cpp create mode 100644 Cantera/src/thermo/VPSSMgr_Water_ConstVol.h create mode 100644 Cantera/src/thermo/VPSSMgr_Water_HKFT.cpp create mode 100644 Cantera/src/thermo/VPSSMgr_Water_HKFT.h create mode 100644 Cantera/src/thermo/VPSSMgr_types.h 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