VPStandardStateTP.cpp

Go to the documentation of this file.
00001 /**
00002  *  @file VPStandardStateTP.cpp
00003  * Definition file for a derived class of ThermoPhase that handles
00004  * variable pressure standard state methods for calculating
00005  * thermodynamic properties (see \ref thermoprops and
00006  * class \link Cantera::VPStandardStateTP VPStandardStateTP\endlink).
00007  */
00008 /*
00009  * Copywrite (2005) Sandia Corporation. Under the terms of 
00010  * Contract DE-AC04-94AL85000 with Sandia Corporation, the
00011  * U.S. Government retains certain rights in this software.
00012  */
00013 /*
00014  *  $Author: hkmoffa $
00015  *  $Date: 2010-01-17 12:05:46 -0500 (Sun, 17 Jan 2010) $
00016  *  $Revision: 385 $
00017  */
00018 
00019 // turn off warnings under Windows
00020 #ifdef WIN32
00021 #pragma warning(disable:4786)
00022 #pragma warning(disable:4503)
00023 #endif
00024 
00025 #include "VPStandardStateTP.h"
00026 #include "VPSSMgr.h"
00027 #include "PDSS.h"
00028 
00029 using namespace std;
00030 
00031 namespace Cantera {
00032 
00033   /*
00034    * Default constructor
00035    */
00036   VPStandardStateTP::VPStandardStateTP() :
00037     ThermoPhase(),
00038     m_Pcurrent(OneAtm),
00039     m_Tlast_ss(-1.0),
00040     m_Plast_ss(-1.0),
00041     m_P0(OneAtm),
00042     m_VPSS_ptr(0)
00043   {
00044   }
00045 
00046   /*
00047    * Copy Constructor:
00048    *
00049    *  Note this stuff will not work until the underlying phase
00050    *  has a working copy constructor.
00051    *
00052    *  The copy constructor just calls the assignment operator
00053    *  to do the heavy lifting.
00054    */
00055   VPStandardStateTP::VPStandardStateTP(const VPStandardStateTP &b) :
00056     ThermoPhase(),
00057     m_Pcurrent(OneAtm),
00058     m_Tlast_ss(-1.0),
00059     m_Plast_ss(-1.0),
00060     m_P0(OneAtm),
00061     m_VPSS_ptr(0)
00062   {
00063     VPStandardStateTP::operator=(b);
00064   }
00065 
00066   /*
00067    * operator=()
00068    *
00069    *  Note this stuff will not work until the underlying phase
00070    *  has a working assignment operator
00071    */
00072   VPStandardStateTP& 
00073   VPStandardStateTP::operator=(const VPStandardStateTP &b) {
00074     if (&b != this) {
00075       /*
00076        * Mostly, this is a passthrough to the underlying
00077        * assignment operator for the ThermoPhase parent object.
00078        */
00079       ThermoPhase::operator=(b);
00080       /*
00081        * However, we have to handle data that we own.
00082        */
00083       m_Pcurrent     = b.m_Pcurrent;
00084       m_Tlast_ss     = b.m_Tlast_ss;
00085       m_Plast_ss     = b.m_Plast_ss;
00086       m_P0        = b.m_P0;
00087 
00088       /*
00089        * Duplicate the pdss objects
00090        */
00091       if (m_PDSS_storage.size() > 0) {
00092         for (int k = 0; k < (int) m_PDSS_storage.size(); k++) {
00093           delete(m_PDSS_storage[k]);
00094         }
00095       }
00096       m_PDSS_storage.resize(m_kk);
00097       for (int k = 0; k < m_kk; k++) {
00098         PDSS *ptmp = b.m_PDSS_storage[k];
00099         m_PDSS_storage[k] = ptmp->duplMyselfAsPDSS();
00100       }
00101 
00102       /*
00103        *  Duplicate the VPSS Manager object that conducts the calculations
00104        */
00105       if (m_VPSS_ptr) {
00106         delete m_VPSS_ptr; 
00107         m_VPSS_ptr = 0;
00108       }
00109       m_VPSS_ptr = (b.m_VPSS_ptr)->duplMyselfAsVPSSMgr();
00110 
00111       /*
00112        *  The VPSSMgr object contains shallow pointers. Whenever you have shallow
00113        *  pointers, they have to be fixed up to point to the correct objects refering
00114        *  back to this ThermoPhase's properties.
00115        */
00116       m_VPSS_ptr->initAllPtrs(this, m_spthermo);
00117       /*
00118        *  The PDSS objects contains shallow pointers. Whenever you have shallow
00119        *  pointers, they have to be fixed up to point to the correct objects refering
00120        *  back to this ThermoPhase's properties. This function also sets m_VPSS_ptr
00121        *  so it occurs after m_VPSS_ptr is set.
00122        */
00123       for (int k = 0; k < m_kk; k++) {
00124         PDSS *ptmp = m_PDSS_storage[k];
00125         ptmp->initAllPtrs(this, m_VPSS_ptr, m_spthermo);
00126       }
00127       /*
00128        *  Ok, the VPSSMgr object is ready for business.
00129        *  We need to resync the temperature and the pressure of the new standard states
00130        *  with what is storred in this object.
00131        */
00132       m_VPSS_ptr->setState_TP(m_Tlast_ss, m_Plast_ss);
00133     }
00134     return *this;
00135   }
00136   //====================================================================================================================
00137   /*
00138    * ~VPStandardStateTP():   (virtual)
00139    *
00140    */
00141   VPStandardStateTP::~VPStandardStateTP() {
00142     for (int k = 0; k < (int) m_PDSS_storage.size(); k++) {
00143       delete(m_PDSS_storage[k]);
00144     }
00145     delete m_VPSS_ptr;
00146   }
00147 
00148   /*
00149    * Duplication function.
00150    *  This calls the copy constructor for this object.
00151    */
00152   ThermoPhase* VPStandardStateTP::duplMyselfAsThermoPhase() const {
00153     VPStandardStateTP* vptp = new VPStandardStateTP(*this);
00154     return (ThermoPhase *) vptp;
00155   }
00156 
00157   // This method returns the convention used in specification
00158   // of the standard state, of which there are currently two,
00159   // temperature based, and variable pressure based.
00160   /*
00161    * Currently, there are two standard state conventions:
00162    *  - Temperature-based activities
00163    *   cSS_CONVENTION_TEMPERATURE 0
00164    *      - default
00165    *
00166    *  -  Variable Pressure and Temperature -based activities
00167    *   cSS_CONVENTION_VPSS 1
00168    */
00169   int VPStandardStateTP::standardStateConvention() const {
00170     return cSS_CONVENTION_VPSS;
00171   }
00172 
00173 
00174   /*
00175    * ------------Molar Thermodynamic Properties -------------------------
00176    */
00177   
00178   
00179   doublereal VPStandardStateTP::err(std::string msg) const {
00180     throw CanteraError("VPStandardStateTP","Base class method "
00181                        +msg+" called. Equation of state type: "+int2str(eosType()));
00182     return 0;
00183   }
00184   
00185   /*
00186    * ---- Partial Molar Properties of the Solution -----------------
00187    */
00188   
00189   /*
00190    * Get the array of non-dimensional species chemical potentials
00191    * These are partial molar Gibbs free energies.
00192    * \f$ \mu_k / \hat R T \f$.
00193    * Units: unitless
00194    *
00195    * We close the loop on this function, here, calling
00196    * getChemPotentials() and then dividing by RT.
00197    */
00198   void VPStandardStateTP::getChemPotentials_RT(doublereal* muRT) const{
00199     getChemPotentials(muRT);
00200     doublereal invRT = 1.0 / _RT();
00201     for (int k = 0; k < m_kk; k++) {
00202       muRT[k] *= invRT;
00203     }
00204   }
00205   
00206   /*
00207    * ----- Thermodynamic Values for the Species Standard States States ----
00208    */
00209   void VPStandardStateTP::getStandardChemPotentials(doublereal* g) const {
00210     getGibbs_RT(g);
00211     doublereal RT = _RT();
00212     for (int k = 0; k < m_kk; k++) {
00213       g[k] *= RT;
00214     }
00215   } 
00216   
00217   inline
00218   void VPStandardStateTP::getEnthalpy_RT(doublereal* hrt) const {
00219     updateStandardStateThermo();
00220     m_VPSS_ptr->getEnthalpy_RT(hrt);
00221   }
00222 
00223   //================================================================================================
00224 #ifdef H298MODIFY_CAPABILITY
00225   // Modify the value of the 298 K Heat of Formation of one species in the phase (J kmol-1)
00226   /*
00227    *   The 298K heat of formation is defined as the enthalpy change to create the standard state
00228    *   of the species from its constituent elements in their standard states at 298 K and 1 bar.
00229    *
00230    *   @param  k           Species k
00231    *   @param  Hf298New    Specify the new value of the Heat of Formation at 298K and 1 bar                      
00232    */
00233   void VPStandardStateTP::modifyOneHf298SS(const int k, const doublereal Hf298New) {
00234     m_spthermo->modifyOneHf298(k, Hf298New);
00235     m_Tlast_ss += 0.0001234;
00236   }
00237 #endif
00238   //================================================================================================
00239   void VPStandardStateTP::getEntropy_R(doublereal* srt) const {
00240     updateStandardStateThermo();
00241     m_VPSS_ptr->getEntropy_R(srt);
00242   }
00243   
00244   inline
00245   void VPStandardStateTP::getGibbs_RT(doublereal* grt) const {
00246     updateStandardStateThermo();
00247     m_VPSS_ptr->getGibbs_RT(grt);
00248   }
00249   
00250   inline
00251   void VPStandardStateTP::getPureGibbs(doublereal* g) const {
00252     updateStandardStateThermo();
00253     m_VPSS_ptr->getStandardChemPotentials(g);
00254   }
00255 
00256   void VPStandardStateTP::getIntEnergy_RT(doublereal* urt) const {
00257     updateStandardStateThermo();
00258     m_VPSS_ptr->getIntEnergy_RT(urt);
00259   }
00260 
00261   void VPStandardStateTP::getCp_R(doublereal* cpr) const {
00262     updateStandardStateThermo();
00263     m_VPSS_ptr->getCp_R(cpr);
00264   }
00265 
00266   void VPStandardStateTP::getStandardVolumes(doublereal *vol) const {
00267     updateStandardStateThermo();
00268     m_VPSS_ptr->getStandardVolumes(vol);
00269   }
00270 
00271   /*
00272    * ----- Thermodynamic Values for the Species Reference States ----
00273    */
00274 
00275   /*
00276    *  Returns the vector of nondimensional enthalpies of the
00277    *  reference state at the current temperature of the solution and
00278    *  the reference pressure for the species.
00279    */
00280   void VPStandardStateTP::getEnthalpy_RT_ref(doublereal *hrt) const {
00281     updateStandardStateThermo();
00282     m_VPSS_ptr->getEnthalpy_RT_ref(hrt);
00283   }
00284     
00285   /*
00286    *  Returns the vector of nondimensional
00287    *  enthalpies of the reference state at the current temperature
00288    *  of the solution and the reference pressure for the species.
00289    */
00290   void VPStandardStateTP::getGibbs_RT_ref(doublereal *grt) const {
00291     updateStandardStateThermo();
00292     m_VPSS_ptr->getGibbs_RT_ref(grt);
00293   }
00294         
00295   /*
00296    *  Returns the vector of the
00297    *  gibbs function of the reference state at the current temperature
00298    *  of the solution and the reference pressure for the species.
00299    *  units = J/kmol
00300    *
00301    *  This is filled in here so that derived classes don't have to
00302    *  take care of it.
00303    */
00304   void VPStandardStateTP::getGibbs_ref(doublereal *g) const {
00305     updateStandardStateThermo();
00306     m_VPSS_ptr->getGibbs_ref(g);
00307   }
00308 
00309   const vector_fp & VPStandardStateTP::Gibbs_RT_ref() const {
00310     updateStandardStateThermo();
00311     return m_VPSS_ptr->Gibbs_RT_ref();
00312   }
00313 
00314   /*
00315    *  Returns the vector of nondimensional
00316    *  entropies of the reference state at the current temperature
00317    *  of the solution and the reference pressure for the species.
00318    */
00319   void VPStandardStateTP::getEntropy_R_ref(doublereal *er) const {
00320     updateStandardStateThermo();
00321     m_VPSS_ptr->getEntropy_R_ref(er);
00322   }
00323      
00324   /*
00325    *  Returns the vector of nondimensional
00326    *  constant pressure heat capacities of the reference state
00327    *  at the current temperature of the solution
00328    *  and reference pressure for the species.
00329    */
00330   void VPStandardStateTP::getCp_R_ref(doublereal *cpr) const {
00331     updateStandardStateThermo();
00332     m_VPSS_ptr->getCp_R_ref(cpr);
00333   }
00334   
00335   /*
00336    *  Get the molar volumes of the species reference states at the current
00337    *  <I>T</I> and <I>P_ref</I> of the solution.
00338    *
00339    * units = m^3 / kmol
00340    */
00341   void VPStandardStateTP::getStandardVolumes_ref(doublereal *vol) const {
00342     updateStandardStateThermo();
00343     m_VPSS_ptr->getStandardVolumes_ref(vol);
00344   }
00345 
00346   /*
00347    * Perform initializations after all species have been
00348    * added.
00349    */
00350   void VPStandardStateTP::initThermo() {
00351     initLengths();
00352     ThermoPhase::initThermo();
00353     m_VPSS_ptr->initThermo();
00354     for (int k = 0; k < m_kk; k++) {
00355       PDSS *kPDSS = m_PDSS_storage[k];
00356       if (kPDSS) {
00357         kPDSS->initThermo();
00358       }
00359     }
00360   }
00361   
00362   void VPStandardStateTP::setVPSSMgr(VPSSMgr *vp_ptr) {
00363     m_VPSS_ptr = vp_ptr;
00364   }
00365 
00366   /*
00367    * Initialize the internal lengths.
00368    *       (this is not a virtual function)
00369    */
00370   void VPStandardStateTP::initLengths() {
00371     m_kk = nSpecies();
00372 
00373   }
00374 
00375 
00376   void VPStandardStateTP::setTemperature(const doublereal temp) {
00377     setState_TP(temp, m_Pcurrent);
00378     updateStandardStateThermo();
00379   }
00380 
00381   void VPStandardStateTP::setPressure(doublereal p) {
00382     setState_TP(temperature(), p);
00383     updateStandardStateThermo();
00384   }
00385 
00386   void VPStandardStateTP::calcDensity() {
00387     err("VPStandardStateTP::calcDensity() called, but EOS for phase is not known");
00388   }
00389 
00390 
00391   void VPStandardStateTP::setState_TP(doublereal t, doublereal pres) {
00392     /*
00393      *  A pretty tricky algorithm is needed here, due to problems involving
00394      *  standard states of real fluids. For those cases you need 
00395      *  to combine the T and P specification for the standard state, or else
00396      *  you may venture into the forbidden zone, especially when nearing the
00397      *  triple point.
00398      *     Therefore, we need to do the standard state thermo calc with the
00399      *  (t, pres) combo.
00400      */
00401     State::setTemperature(t);
00402     m_Pcurrent = pres;
00403     updateStandardStateThermo();
00404     /*
00405      * Now, we still need to do the calculations for general ThermoPhase objects.
00406      * So, we switch back to a virtual function call, setTemperature, and 
00407      * setPressure to recalculate stuff for child ThermoPhase objects of 
00408      * the VPStandardStateTP object. At this point,
00409      * we haven't touched m_tlast or m_plast, so some calculations may still
00410      * need to be done at the ThermoPhase object level.
00411      */
00412     //setTemperature(t);
00413     //setPressure(pres);
00414     calcDensity();
00415   }
00416 
00417 
00418 
00419   void 
00420   VPStandardStateTP::createInstallPDSS(int k,  const XML_Node& s,
00421                                        const XML_Node * phaseNode_ptr) {
00422     if ((int) m_PDSS_storage.size() < k+1) {
00423       m_PDSS_storage.resize(k+1,0);
00424     }
00425     if (m_PDSS_storage[k] != 0) {
00426       delete m_PDSS_storage[k] ;
00427     }
00428     m_PDSS_storage[k] = m_VPSS_ptr->createInstallPDSS(k, s, phaseNode_ptr);
00429   }
00430 
00431   PDSS *
00432   VPStandardStateTP::providePDSS(int k) {
00433     return m_PDSS_storage[k];
00434   }
00435 
00436   const PDSS *
00437   VPStandardStateTP::providePDSS(int k) const {
00438     return m_PDSS_storage[k];
00439   }
00440 
00441   /*
00442    *   Import and initialize a ThermoPhase object
00443    *
00444    * param phaseNode This object must be the phase node of a
00445    *             complete XML tree
00446    *             description of the phase, including all of the
00447    *             species data. In other words while "phase" must
00448    *             point to an XML phase object, it must have
00449    *             sibling nodes "speciesData" that describe
00450    *             the species in the phase.
00451    * param id   ID of the phase. If nonnull, a check is done
00452    *             to see if phaseNode is pointing to the phase
00453    *             with the correct id.
00454    *
00455    * This routine initializes the lengths in the current object and
00456    * then calls the parent routine.
00457    */
00458   void VPStandardStateTP::initThermoXML(XML_Node& phaseNode, std::string id) {
00459     VPStandardStateTP::initLengths();
00460    
00461     //m_VPSS_ptr->initThermo();
00462     for (int k = 0; k < m_kk; k++) {
00463       PDSS *kPDSS = m_PDSS_storage[k];
00464       AssertTrace(kPDSS != 0);
00465       if (kPDSS) {
00466         kPDSS->initThermoXML(phaseNode, id);
00467       }
00468     }
00469     m_VPSS_ptr->initThermoXML(phaseNode, id);
00470     ThermoPhase::initThermoXML(phaseNode, id);
00471   }
00472 
00473 
00474   VPSSMgr *VPStandardStateTP::provideVPSSMgr() {
00475     return m_VPSS_ptr;
00476   }
00477  
00478   /*
00479    * void _updateStandardStateThermo()            (protected, virtual, const)
00480    *
00481    * If m_useTmpStandardStateStorage is true,
00482    * This function must be called for every call to functions in this
00483    * class that need standard state properties.
00484    * Child classes may require that it be called even if  m_useTmpStandardStateStorage
00485    * is not true.
00486    * It checks to see whether the temperature has changed and
00487    * thus the ss thermodynamics functions for all of the species
00488    * must be recalculated.
00489    *
00490    * This 
00491    */                    
00492   void VPStandardStateTP::_updateStandardStateThermo() const {
00493     double Tnow = temperature();
00494     m_Plast_ss = m_Pcurrent;
00495     m_Tlast_ss = Tnow;
00496     AssertThrowMsg(m_VPSS_ptr != 0, "VPStandardStateTP::_updateStandardStateThermo()",
00497                    "Probably indicates that ThermoPhase object wasn't initialized correctly");
00498     m_VPSS_ptr->setState_TP(Tnow, m_Pcurrent);
00499   }
00500 
00501   void VPStandardStateTP::updateStandardStateThermo() const {
00502     double Tnow = temperature();
00503     if (Tnow != m_Tlast_ss || m_Pcurrent != m_Plast_ss) {
00504       _updateStandardStateThermo();
00505     }
00506   }
00507 }
00508 
00509 
Generated by  doxygen 1.6.3