SingleSpeciesTP.cpp

Go to the documentation of this file.
00001 /**
00002  *  @file SingleSpeciesTP.cpp
00003  *  Definitions for the %SingleSpeciesTP class, which is a filter class for %ThermoPhase,
00004  *  that eases the construction of single species phases 
00005  *  ( see \ref thermoprops and class \link Cantera::SingleSpeciesTP SingleSpeciesTP\endlink).
00006  */
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 /*
00015  *  $Author: hkmoffa $
00016  *  $Date: 2010-01-15 15:22:09 -0500 (Fri, 15 Jan 2010) $
00017  *  $Revision: 378 $
00018  */
00019 
00020 #include "SingleSpeciesTP.h"
00021 
00022 using namespace std;
00023 
00024 namespace Cantera {
00025 
00026   /*
00027    * --------------  Constructors ------------------------------------
00028    *
00029    */
00030 
00031   // Base empty constructor. 
00032   /*
00033    *   Base constructor -> does nothing but called the inherited
00034    *   class constructor
00035    */
00036   SingleSpeciesTP::SingleSpeciesTP() :
00037     ThermoPhase(),
00038     m_tmin(0.0),
00039     m_tmax(0.0),
00040     m_press(OneAtm),
00041     m_p0(OneAtm),
00042     m_tlast(-1.0) 
00043   {
00044   }
00045 
00046 
00047   //! Copy constructor
00048   /*!
00049    * @param right Object to be copied
00050    */
00051   SingleSpeciesTP::SingleSpeciesTP(const SingleSpeciesTP &right):
00052     ThermoPhase(),
00053     m_tmin(0.0),
00054     m_tmax(0.0),
00055     m_press(OneAtm),
00056     m_p0(OneAtm),
00057     m_tlast(-1.0) 
00058   {
00059     *this = operator=(right);
00060   }
00061   
00062   //! Assignment operator
00063   /*!
00064    * @param right Object to be copied
00065    */
00066   SingleSpeciesTP & SingleSpeciesTP::operator=(const SingleSpeciesTP & right) {
00067    if (&right != this) {
00068       ThermoPhase::operator=(right);
00069       m_tmin       = right.m_tmin;
00070       m_tmax       = right.m_tmax;
00071       m_press      = right.m_press;
00072       m_p0         = right.m_p0;
00073       m_tlast      = right.m_tlast;
00074       m_h0_RT      = right.m_h0_RT;
00075       m_cp0_R      = right.m_cp0_R;
00076       m_s0_R       = right.m_s0_R;
00077     }
00078     return *this;
00079   }
00080   
00081   /*
00082    *  destructor -> does nothing but implicitly calls the inherited
00083    *                class destructors.
00084    */
00085   SingleSpeciesTP::~SingleSpeciesTP()
00086   {
00087   }
00088 
00089   //! Duplication function
00090   /*!
00091    * This virtual function is used to create a duplicate of the
00092    * current phase. It's used to duplicate the phase when given
00093    * a ThermoPhase pointer to the phase.
00094    *
00095    * @return It returns a ThermoPhase pointer.
00096    */
00097   ThermoPhase *SingleSpeciesTP::duplMyselfAsThermoPhase() const {
00098     SingleSpeciesTP *stp = new SingleSpeciesTP(*this);
00099     return (ThermoPhase *) stp;
00100   }
00101 
00102   /**
00103    *   
00104    * ------------------- Utilities ----------------------------------  
00105    * 
00106    */
00107   
00108   /**
00109    * eosType():
00110    *      Creates an error because this is not a fully formed
00111    *      class
00112    */
00113   int SingleSpeciesTP::eosType() const {
00114     err("eosType");
00115     return -1;
00116   }
00117 
00118   /**
00119    * ------------ Molar Thermodynamic Properties --------------------
00120    * 
00121    *
00122    *   For this single species template, the molar properties of
00123    *   the mixture are identified with the partial molar properties
00124    *   of species number 0. The partial molar property routines
00125    *   are called to evaluate these functions.
00126    */
00127     
00128   /**
00129    * enthalpy_mole():
00130    *
00131    *  Molar enthalpy. Units: J/kmol. 
00132    */
00133   doublereal SingleSpeciesTP::enthalpy_mole() const {
00134     double hbar;
00135     getPartialMolarEnthalpies(&hbar);
00136     return hbar;
00137   }
00138 
00139   /**
00140    * enthalpy_mole():
00141    *
00142    *  Molar internal energy. Units: J/kmol. 
00143    */
00144   doublereal SingleSpeciesTP::intEnergy_mole() const {
00145     double ubar;
00146     getPartialMolarIntEnergies(&ubar);
00147     return ubar;
00148   }
00149 
00150   /**
00151    * entropy_mole():
00152    *
00153    *  Molar entropy of the mixture. Units: J/kmol/K. 
00154    */
00155   doublereal SingleSpeciesTP::entropy_mole() const {
00156     double sbar;
00157     getPartialMolarEntropies(&sbar);
00158     return sbar;
00159   }
00160 
00161   /**
00162    * gibbs_mole():
00163    *
00164    *  Molar Gibbs free energy of the mixture. Units: J/kmol/K. 
00165    */
00166   doublereal SingleSpeciesTP::gibbs_mole() const {
00167     double gbar;
00168     /*
00169      * Get the chemical potential of the first species.
00170      * This is the same as the partial molar Gibbs
00171      * free energy.
00172      */
00173     getChemPotentials(&gbar);
00174     return gbar;
00175   }
00176 
00177   /**
00178    * cp_mole():
00179    *
00180    *  Molar heat capacity at constant pressure of the mixture. 
00181    *  Units: J/kmol/K. 
00182    */
00183   doublereal SingleSpeciesTP::cp_mole() const {
00184     double cpbar;
00185     /*
00186      * Really should have a partial molar heat capacity 
00187      * function in ThermoPhase. However, the standard
00188      * state heat capacity will do fine here for now.
00189      */
00190     //getPartialMolarCp(&cpbar);
00191     getCp_R(&cpbar);
00192     cpbar *= GasConstant;
00193     return cpbar;
00194   }
00195 
00196   /*
00197    * cv_mole():
00198    *
00199    *  Molar heat capacity at constant volume of the mixture. 
00200    *  Units: J/kmol/K. 
00201    *
00202    *  For single species, we go directory to the 
00203    *  general Cp - Cv relation
00204    *
00205    *  Cp = Cv + alpha**2 * V * T / beta
00206    *
00207    * where 
00208    *     alpha = volume thermal expansion coefficient
00209    *     beta  = isothermal compressibility
00210    */
00211   doublereal SingleSpeciesTP::cv_mole() const {
00212     doublereal cvbar = cp_mole();
00213     doublereal alpha = thermalExpansionCoeff();
00214     doublereal beta = isothermalCompressibility();
00215     doublereal molecW = molecularWeight(0);
00216     doublereal V = molecW/density();
00217     doublereal T = temperature();
00218     if (beta != 0.0) {
00219       cvbar -= alpha * alpha * V * T / beta;
00220     }
00221     return cvbar;
00222   }
00223 
00224   /*
00225    * ----------- Chemical Potentials and Activities ----------------------
00226    */
00227 
00228   /*
00229    * ----------- Partial Molar Properties of the Solution -----------------
00230    *
00231    *  These are calculated by reference to the standard state properties
00232    *  of the zeroeth species.
00233    */
00234 
00235   
00236   // Get the array of chemical potentials at unit activity 
00237   /*
00238    * These are the standard state chemical potentials.  \f$ \mu^0_k \f$.
00239    *
00240    *  @param mu   On return, Contains the chemical potential of the single species
00241    *              and the phase. Units are J / kmol . Length = 1
00242    */
00243   void SingleSpeciesTP::getChemPotentials(doublereal* mu) const {
00244     getStandardChemPotentials(mu);
00245   }
00246 
00247   
00248   //  Get the array of non-dimensional species chemical potentials
00249   // These are partial molar Gibbs free energies.
00250   /*
00251    *  These are the standard state dimensionless chemical potentials. 
00252    *  \f$ \mu_k / \hat R T \f$.
00253    *
00254    * Units: unitless
00255    *
00256    *  @param murt   On return, Contains the chemical potential / RT of the single species
00257    *                and the phase. Units are unitless. Length = 1
00258    */
00259   void SingleSpeciesTP::getChemPotentials_RT(doublereal* murt) const {
00260     getStandardChemPotentials(murt);
00261     double rt = GasConstant * temperature();
00262     murt[0] /= rt;
00263   }
00264 
00265   // Get the species electrochemical potentials. Units: J/kmol.
00266   /*
00267    * This method adds a term \f$ Fz_k \phi_k \f$ to 
00268    * each chemical potential.
00269    *
00270    * This is resolved here. A single  species phase
00271    * is not allowed to have anything other than a zero charge.
00272    *
00273    *  @param murt   On return, Contains the chemical potential / RT of the single species
00274    *                and the phase. Units are unitless. Length = 1
00275    */
00276   void SingleSpeciesTP::getElectrochemPotentials(doublereal* mu) const {
00277     getChemPotentials(mu);
00278   }
00279 
00280   // Get the species partial molar enthalpies. Units: J/kmol.
00281   /*
00282    * These are the phase enthalpies.  \f$ h_k \f$.
00283    *
00284    *  @param hbar On return, Contains the enthalpy of the single species
00285    *              and the phase. Units are J / kmol . Length = 1
00286    */
00287   void SingleSpeciesTP::
00288   getPartialMolarEnthalpies(doublereal* hbar) const {
00289     double _rt = GasConstant * temperature();
00290     getEnthalpy_RT(hbar);
00291     hbar[0] *= _rt;
00292   }
00293 
00294   // Get the species partial molar internal energies. Units: J/kmol.
00295   /*
00296    * These are the phase internal energies.  \f$ u_k \f$.
00297    *
00298    * This  member function is resolved here. A single species phase obtains its
00299    * thermo from the standard state function.
00300    *
00301    *  @param ubar On return, Contains the internal energy of the single species
00302    *              and the phase. Units are J / kmol . Length = 1
00303    */
00304   void SingleSpeciesTP::
00305   getPartialMolarIntEnergies(doublereal* ubar) const {
00306     double _rt = GasConstant * temperature();
00307     getIntEnergy_RT(ubar);
00308     ubar[0] *= _rt;
00309   }
00310 
00311   // Get the species partial molar entropy. Units: J/kmol K.
00312   /*
00313    * This is the phase entropy.  \f$ s(T,P) = s_o(T,P) \f$.
00314    *
00315    * This member function is resolved here. A single species phase obtains its
00316    * thermo from the standard state function.
00317    *
00318    *  @param sbar On return, Contains the entropy of the single species
00319    *              and the phase. Units are J / kmol / K . Length = 1
00320    */
00321   void SingleSpeciesTP::
00322   getPartialMolarEntropies(doublereal* sbar) const {
00323     getEntropy_R(sbar);
00324     sbar[0] *= GasConstant;
00325   }
00326 
00327   // Get the species partial molar Heat Capacities. Units: J/ kmol K.
00328   /*
00329    * This is the phase heat capacity.  \f$ Cp(T,P) = Cp_o(T,P) \f$.
00330    *
00331    * This member function is resolved here. A single species phase obtains its
00332    * thermo from the standard state function.
00333    *
00334    *  @param cpbar On return, Contains the heat capacity of the single species
00335    *              and the phase. Units are J / kmol / K . Length = 1
00336    */
00337   void SingleSpeciesTP::getPartialMolarCp(doublereal* cpbar) const {
00338     getCp_R(cpbar);
00339     cpbar[0] *= GasConstant;
00340   }
00341   
00342   // Get the species partial molar volumes. Units: m^3/kmol.
00343   /*
00344    * This is the phase molar volume.  \f$ V(T,P) = V_o(T,P) \f$.
00345    *
00346    * This member function is resolved here. A single species phase obtains its
00347    * thermo from the standard state function.
00348    *
00349    *  @param cpbar On return, Contains the molar volume of the single species
00350    *              and the phase. Units are m^3 / kmol. Length = 1
00351    */
00352   void SingleSpeciesTP::getPartialMolarVolumes(doublereal* vbar) const {
00353     double mw = molecularWeight(0);
00354     double dens = density();
00355     vbar[0] = mw / dens;
00356   }
00357 
00358   /* 
00359    * ----- Properties of the Standard State of the Species in the Solution
00360    *  -----
00361    */
00362 
00363   /*
00364    * Get the dimensional Gibbs functions for the standard
00365    * state of the species at the current T and P.
00366    */
00367   void SingleSpeciesTP::getPureGibbs(doublereal* gpure) const {
00368     getGibbs_RT(gpure);
00369     gpure[0] *= GasConstant * temperature();
00370   }
00371 
00372  
00373   // Get the molar volumes of each species in their standard
00374   // states at the current  <I>T</I> and <I>P</I> of the solution.
00375   /*
00376    *   units = m^3 / kmol
00377    *
00378    * We resolve this function at this level, by assigning 
00379    * the molecular weight divided by the phase density
00380    *
00381    * @param vbar On output this contains the standard volume of the species
00382    *             and phase (m^3/kmol). Vector of length 1
00383    */
00384   void SingleSpeciesTP::getStandardVolumes(doublereal* vbar) const {
00385     double mw = molecularWeight(0);
00386     double dens = density();
00387     vbar[0] = mw / dens;
00388   }
00389 
00390   /*
00391    * ---- Thermodynamic Values for the Species Reference States -------
00392    */
00393 
00394 
00395   /**
00396    *  Returns the vector of nondimensional
00397    *  enthalpies of the reference state at the current temperature
00398    *  of the solution and the reference pressure for the species.
00399    *
00400    * 
00401    */
00402   void SingleSpeciesTP::getEnthalpy_RT_ref(doublereal *hrt) const {
00403     _updateThermo();
00404     hrt[0] = m_h0_RT[0];
00405   }
00406 
00407 
00408   /**
00409    *  Returns the vector of nondimensional
00410    *  enthalpies of the reference state at the current temperature
00411    *  of the solution and the reference pressure for the species.
00412    */
00413   void SingleSpeciesTP::getGibbs_RT_ref(doublereal *grt) const {
00414     _updateThermo();
00415     grt[0] = m_h0_RT[0] - m_s0_R[0];
00416   }
00417 
00418   /**
00419    *  Returns the vector of the 
00420    *  gibbs function of the reference state at the current temperature
00421    *  of the solution and the reference pressure for the species.
00422    *  units = J/kmol
00423    */
00424   void SingleSpeciesTP::getGibbs_ref(doublereal *g) const {
00425     getGibbs_RT_ref(g);
00426     g[0] *= GasConstant * temperature();
00427   }
00428        
00429   /**
00430    *  Returns the vector of nondimensional
00431    *  entropies of the reference state at the current temperature
00432    *  of the solution and the reference pressure for the species.
00433    */
00434   void SingleSpeciesTP::getEntropy_R_ref(doublereal *er) const {
00435     _updateThermo();
00436     er[0] = m_s0_R[0];
00437   }
00438 
00439   /**
00440    * Get the nondimensional Gibbs functions for the standard
00441    * state of the species at the current T and reference pressure
00442    * for the species.
00443    */
00444   void SingleSpeciesTP::getCp_R_ref(doublereal* cpr) const {
00445     _updateThermo();
00446     cpr[0] = m_cp0_R[0];
00447   }
00448 
00449   /*
00450    * ------------------ Setting the State ------------------------
00451    */
00452 
00453 
00454   void SingleSpeciesTP::setState_TPX(doublereal t, doublereal p, 
00455                                      const doublereal* x) {
00456     setTemperature(t); setPressure(p);
00457   }
00458 
00459   void SingleSpeciesTP::setState_TPX(doublereal t, doublereal p, 
00460                                      compositionMap& x) {
00461     setTemperature(t); setPressure(p);
00462   }
00463 
00464   void SingleSpeciesTP::setState_TPX(doublereal t, doublereal p, 
00465                                      const std::string& x) {
00466     setTemperature(t); setPressure(p);
00467   }        
00468 
00469   void SingleSpeciesTP::setState_TPY(doublereal t, doublereal p, 
00470                                      const doublereal* y) {
00471     setTemperature(t); setPressure(p);
00472   }
00473 
00474   void SingleSpeciesTP::setState_TPY(doublereal t, doublereal p, 
00475                                      compositionMap& y) {
00476     setTemperature(t); setPressure(p);
00477   }
00478         
00479   void SingleSpeciesTP::setState_TPY(doublereal t, doublereal p, 
00480                                      const std::string& y) {
00481     setTemperature(t); setPressure(p);
00482   }
00483 
00484   void SingleSpeciesTP::setState_PX(doublereal p, doublereal* x) {
00485     if (x[0] != 1.0) {
00486       err("setStatePX -> x[0] not 1.0");
00487     }
00488     setPressure(p);
00489   }
00490 
00491   void SingleSpeciesTP::setState_PY(doublereal p, doublereal* y) {
00492     if (y[0] != 1.0) {
00493       err("setStatePY -> x[0] not 1.0");
00494     }
00495     setPressure(p);
00496   }
00497 
00498   void SingleSpeciesTP::setState_HP(doublereal h, doublereal p, 
00499                                     doublereal tol) {
00500     doublereal dt;
00501     setPressure(p);
00502     for (int n = 0; n < 50; n++) {
00503       dt = (h - enthalpy_mass())/cp_mass();
00504       if (dt > 100.0) dt = 100.0;
00505       else if (dt < -100.0) dt = -100.0; 
00506       setState_TP(temperature() + dt, p);
00507       if (fabs(dt) < tol) {
00508         return;
00509       }
00510     }
00511     throw CanteraError("setState_HP","no convergence. dt = " + fp2str(dt));
00512   }
00513 
00514   void SingleSpeciesTP::setState_UV(doublereal u, doublereal v, 
00515                                     doublereal tol) {
00516     doublereal dt;
00517     setDensity(1.0/v);
00518     for (int n = 0; n < 50; n++) {
00519       dt = (u - intEnergy_mass())/cv_mass();
00520       if (dt > 100.0) dt = 100.0;
00521       else if (dt < -100.0) dt = -100.0;
00522       setTemperature(temperature() + dt);
00523       if (fabs(dt) < tol) {
00524         return;
00525       }
00526     }
00527     throw CanteraError("setState_UV",
00528                        "no convergence. dt = " + fp2str(dt)+"\n"
00529                        +"u = "+fp2str(u)+" v = "+fp2str(v)+"\n");
00530   }
00531 
00532   void SingleSpeciesTP::setState_SP(doublereal s, doublereal p, 
00533                                     doublereal tol) {
00534     doublereal dt;
00535     setPressure(p);
00536     for (int n = 0; n < 50; n++) {
00537       dt = (s - entropy_mass())*temperature()/cp_mass();
00538       if (dt > 100.0) dt = 100.0;
00539       else if (dt < -100.0) dt = -100.0; 
00540       setState_TP(temperature() + dt, p);
00541       if (fabs(dt) < tol) {
00542         return;
00543       }
00544     }
00545     throw CanteraError("setState_SP","no convergence. dt = " + fp2str(dt));
00546   }
00547 
00548   void SingleSpeciesTP::setState_SV(doublereal s, doublereal v, 
00549                                     doublereal tol) {
00550     doublereal dt;
00551     setDensity(1.0/v);
00552     for (int n = 0; n < 50; n++) {
00553       dt = (s - entropy_mass())*temperature()/cv_mass();
00554       if (dt > 100.0) dt = 100.0;
00555       else if (dt < -100.0) dt = -100.0; 
00556       setTemperature(temperature() + dt);
00557       if (fabs(dt) < tol) {
00558         return;
00559       }
00560     }
00561     throw CanteraError("setState_SV","no convergence. dt = " + fp2str(dt));
00562   }
00563 
00564   /*
00565    *  This private function throws a cantera exception. It's used when
00566    * this class doesn't have an answer for the question given to it,
00567    *  because the derived class isn't overriding a function.
00568    */
00569   doublereal SingleSpeciesTP::err(std::string msg) const {
00570     throw CanteraError("SingleSpeciesTP","Base class method "
00571                        +msg+" called. Equation of state type: "
00572                        +int2str(eosType()));
00573     return 0;
00574   }
00575 
00576   /*
00577    * @internal Initialize. This method is provided to allow
00578    * subclasses to perform any initialization required after all
00579    * species have been added. For example, it might be used to
00580    * resize internal work arrays that must have an entry for
00581    * each species.  The base class implementation does nothing,
00582    * and subclasses that do not require initialization do not
00583    * need to overload this method.  When importing a CTML phase
00584    * description, this method is called just prior to returning
00585    * from function importPhase.
00586    *
00587    * Inheriting objects should call this function
00588    *
00589    * @see importCTML.cpp
00590    */
00591   void SingleSpeciesTP::initThermo() {
00592  
00593     /*
00594      * Make sure there is one and only one species in this phase.
00595      */
00596     m_kk = nSpecies();
00597     if (m_kk != 1) {
00598       throw CanteraError("initThermo",
00599                          "stoichiometric substances may only contain one species.");
00600     }
00601     doublereal tmin = m_spthermo->minTemp();
00602     doublereal tmax = m_spthermo->maxTemp();
00603     if (tmin > 0.0) m_tmin = tmin;
00604     if (tmax > 0.0) m_tmax = tmax;
00605 
00606     /*
00607      * Store the reference pressure in the variables for the class.
00608      */
00609     m_p0 = refPressure();
00610 
00611     /*
00612      * Resize temporary arrays.
00613      */
00614     int leng = 1;
00615     m_h0_RT.resize(leng);
00616     m_cp0_R.resize(leng);
00617     m_s0_R.resize(leng);
00618 
00619     /*
00620      *  Make sure the species mole fraction is equal to 1.0;
00621      */
00622     double x = 1.0;
00623     setMoleFractions(&x);
00624     /*
00625      * Call the base class initThermo object.
00626      */
00627     ThermoPhase::initThermo();
00628   }
00629 
00630   /*
00631    * _updateThermo():
00632    * 
00633    *        This crucial internal routine calls the species thermo
00634    *        update program to calculate new species Cp0, H0, and
00635    *        S0 whenever the temperature has changed.
00636    */
00637   void SingleSpeciesTP::_updateThermo() const {
00638     doublereal tnow = temperature();
00639     if (m_tlast != tnow) {
00640       m_spthermo->update(tnow, DATA_PTR(m_cp0_R), DATA_PTR(m_h0_RT), 
00641                          DATA_PTR(m_s0_R));
00642       m_tlast = tnow;
00643     }
00644   }
00645 
00646 }
00647 
00648 
00649 
00650 
Generated by  doxygen 1.6.3