ShomateThermo.h

Go to the documentation of this file.
00001 /**
00002  * @file ShomateThermo.h
00003  *   Header for the 2 regions Shomate polynomial
00004  *   for multiple species in a phase, derived from the
00005  *   \link Cantera::SpeciesThermo SpeciesThermo\endlink base class (see \ref mgrsrefcalc and
00006  *   \link Cantera::ShomateThermo ShomateThermo\endlink).
00007  */
00008 /*
00009  * $Id: ShomateThermo.h 306 2009-12-09 17:29:23Z hkmoffa $
00010  */
00011 // Copyright 2001  California Institute of Technology
00012 
00013 
00014 #ifndef CT_SHOMATETHERMO_H
00015 #define CT_SHOMATETHERMO_H
00016 
00017 #include "SpeciesThermoMgr.h"
00018 #include "ShomatePoly.h"
00019 #include "speciesThermoTypes.h"
00020 
00021 namespace Cantera {
00022 
00023   //! A species thermodynamic property manager for the Shomate polynomial parameterization.
00024   /*!
00025    *  This is the parameterization used
00026    *  in the NIST Chemistry WebBook (http://webbook.nist.gov/chemistry)
00027    * The parameterization assumes there are two temperature regions
00028    * each with its own Shomate polynomial representation, for each
00029    * species in the phase.
00030    * 
00031    * \f[
00032    * \tilde{c}_p^0(T) = A + B t + C t^2 + D t^3 + \frac{E}{t^2}
00033    * \f]
00034    * \f[
00035    * \tilde{h}^0(T) = A t + \frac{B t^2}{2} + \frac{C t^3}{3} 
00036    + \frac{D t^4}{4}  - \frac{E}{t}  + F.
00037    * \f]
00038    * \f[
00039    * \tilde{s}^0(T) = A\ln t + B t + \frac{C t^2}{2}  
00040    + \frac{D t^3}{3} - \frac{E}{2t^2}  + G.
00041    * \f]
00042    *
00043    * In the above expressions, the thermodynamic polynomials are expressed
00044    * in dimensional units, but the temperature,\f$ t \f$, is divided by 1000. The
00045    * following dimensions are assumed in the above expressions:
00046    *
00047    *    - \f$ \tilde{c}_p^0(T)\f$ = Heat Capacity (J/gmol*K)
00048    *    - \f$ \tilde{h}^0(T) \f$ = standard Enthalpy (kJ/gmol)
00049    *    - \f$ \tilde{s}^0(T) \f$= standard Entropy (J/gmol*K)
00050    *    - \f$ t \f$= temperature (K) / 1000.
00051    *
00052    *  Note, the polynomial data (i.e., A, ... , G) is entered in dimensional
00053    *        form.
00054    *
00055    *  This is in contrast to the NASA database polynomials which are entered in 
00056    *  nondimensional form (i.e., NASA parameterizes C_p/R, while Shomate
00057    *  parameterizes C_p assuming units of J/gmol*K - and kJ/gmol*K for H).
00058    *  Note, also that the H - H_298.15 equation has units of kJ/gmol, because of
00059    *  the implicit integration of (t = T 1000), which provides a 
00060    *  multiplier of 1000 to the Enthalpy equation.
00061    *
00062    * @ingroup mgrsrefcalc
00063    */
00064   class ShomateThermo : public SpeciesThermo {
00065     
00066   public:
00067 
00068     //! Initialized to the type of parameterization
00069     /*!
00070      * Note, this value is used in some template functions
00071      */
00072     const int ID;
00073 
00074     //! constructor
00075     ShomateThermo() :
00076       ID(SHOMATE),
00077       m_tlow_max(0.0), 
00078       m_thigh_min(1.e30),
00079       m_p0(-1.0),
00080       m_ngroups(0) 
00081     { m_t.resize(7); }
00082 
00083     //! destructor
00084     virtual ~ShomateThermo() {}
00085 
00086     //! Copy Constructor
00087     /*!
00088      * @param right Object to be copied
00089      */
00090     ShomateThermo(const ShomateThermo &right) :
00091       ID(SHOMATE),
00092       m_tlow_max(0.0), 
00093       m_thigh_min(1.e30),
00094       m_p0(-1.0),
00095       m_ngroups(0) 
00096     {
00097       *this = operator=(right);
00098     }
00099 
00100     //! Assignment Operator
00101     /*!
00102      * @param right Object to be copied
00103      */
00104     ShomateThermo& operator=(const ShomateThermo &right) {
00105       if (&right == this) return *this;
00106 
00107       m_high           = right.m_high;
00108       m_low            = right.m_low;
00109       m_index          = right.m_index;
00110       m_tmid           = right.m_tmid;
00111       m_tlow_max       = right.m_tlow_max;
00112       m_thigh_min      = right.m_thigh_min;
00113       m_tlow           = right.m_tlow;
00114       m_thigh          = right.m_thigh;
00115       m_p0             = right.m_p0;
00116       m_ngroups        = right.m_ngroups;
00117       m_t              = right.m_t;
00118       m_group_map      = right.m_group_map;
00119       m_posInGroup_map = right.m_posInGroup_map;
00120 
00121       return *this;
00122     }
00123 
00124    
00125     //! Duplication routine for objects which inherit from 
00126     //! %SpeciesThermo
00127     /*!
00128      *  This virtual routine can be used to duplicate %SpeciesThermo  objects
00129      *  inherited from %SpeciesThermo even if the application only has
00130      *  a pointer to %SpeciesThermo to work with.
00131      *  ->commented out because we first need to add copy constructors
00132      *   and assignment operators to all of the derived classes.
00133      */
00134     virtual SpeciesThermo *duplMyselfAsSpeciesThermo() const {
00135       ShomateThermo *st = new ShomateThermo(*this);
00136       return (SpeciesThermo *) st;
00137     }
00138 
00139     //! Install a new species thermodynamic property
00140     //! parameterization for one species using Shomate polynomials 
00141     //! 
00142     /*!
00143      *  Two temperature regions are assumed.
00144      *
00145      * @param name      Name of the species
00146      * @param index     Species index
00147      * @param type      int flag specifying the type of parameterization to be
00148      *                  installed. 
00149      * @param c         Vector of coefficients for the parameterization. 
00150      *                  There are 15 coefficients for the 2-zone Shomate polynomial.
00151      *                  The first coefficient is the value of Tmid. The next 7 
00152      *                  coefficients are the low temperature range Shomate coefficients.
00153      *                  The last 7 are the high temperature range Shomate coefficients.
00154      *        
00155      * @param minTemp  minimum temperature for which this parameterization
00156      *                 is valid.
00157      * @param maxTemp  maximum temperature for which this parameterization
00158      *                 is valid.
00159      * @param refPressure standard-state pressure for this 
00160      *                    parameterization.
00161      * 
00162      * @see ShomatePoly
00163      * @see ShomatePoly2
00164      */
00165     virtual void install(string name, int index, int type, 
00166                          const doublereal* c,
00167                          doublereal minTemp, doublereal maxTemp, 
00168                          doublereal refPressure) {
00169       int imid = int(c[0]);       // midpoint temp converted to integer
00170       int igrp = m_index[imid];   // has this value been seen before?
00171       if (igrp == 0) {            // if not, prepare new group
00172         vector<ShomatePoly> v;
00173         m_high.push_back(v);
00174         m_low.push_back(v);
00175         m_tmid.push_back(c[0]);
00176         m_index[imid] = igrp = static_cast<int>(m_high.size());
00177         m_ngroups++;
00178       }
00179       m_group_map[index] = igrp;
00180       m_posInGroup_map[index] = (int) m_low[igrp-1].size();
00181       doublereal tlow  = minTemp;
00182       doublereal tmid  = c[0];
00183       doublereal thigh = maxTemp;
00184   
00185       const doublereal* clow = c + 1;
00186       const doublereal* chigh = c + 8;
00187       m_high[igrp-1].push_back(ShomatePoly(index, tmid, thigh, 
00188                                            refPressure, chigh));
00189       m_low[igrp-1].push_back(ShomatePoly(index, tlow, tmid, 
00190                                           refPressure, clow));
00191       if (tlow > m_tlow_max)    m_tlow_max = tlow;
00192       if (thigh < m_thigh_min)  m_thigh_min = thigh;
00193 
00194       if ((int) m_tlow.size() < index + 1) {
00195         m_tlow.resize(index + 1,  tlow);
00196         m_thigh.resize(index + 1, thigh);
00197       }
00198       m_tlow[index] = tlow;
00199       m_thigh[index] = thigh;
00200 
00201       if (m_p0 < 0.0) {
00202         m_p0 = refPressure;
00203       } else if (fabs(m_p0 - refPressure) > 0.1) {
00204         string logmsg =  " WARNING ShomateThermo: New Species, " + name 
00205           +  ", has a different reference pressure, "
00206           + fp2str(refPressure) + ", than existing reference pressure, "        + fp2str(m_p0) + "\n";
00207         writelog(logmsg);
00208         logmsg = "                  This may become a fatal error in the future \n";
00209         writelog(logmsg);
00210       }
00211       m_p0 = refPressure;
00212    
00213     }
00214 
00215     //! Install a new species thermodynamic property
00216     //! parameterization for one species.
00217     /*!
00218      * @param stit_ptr Pointer to the SpeciesThermoInterpType object
00219      *          This will set up the thermo for one species
00220      */
00221     virtual void install_STIT(SpeciesThermoInterpType *stit_ptr) {
00222       throw CanteraError("install_STIT", "not implemented");
00223     }
00224 
00225     //! Like update(), but only updates the single species k.
00226     /*!
00227      * @param k       species index
00228      * @param t       Temperature (Kelvin)
00229      * @param cp_R    Vector of Dimensionless heat capacities.
00230      *                (length m_kk).
00231      * @param h_RT    Vector of Dimensionless enthalpies.
00232      *                (length m_kk).
00233      * @param s_R     Vector of Dimensionless entropies.
00234      *                (length m_kk).
00235      */
00236     virtual void update_one(int k, doublereal t, doublereal* cp_R, 
00237                             doublereal* h_RT, doublereal* s_R) const {
00238 
00239       doublereal tt = 1.e-3*t;
00240       m_t[0] = tt;
00241       m_t[1] = tt*tt;
00242       m_t[2] = m_t[1]*tt;
00243       m_t[3] = 1.0/m_t[1];
00244       m_t[4] = log(tt);
00245       m_t[5] = 1.0/GasConstant;
00246       m_t[6] = 1.0/(GasConstant * t);
00247 
00248       int grp = m_group_map[k];
00249       int pos = m_posInGroup_map[k];
00250       const vector<ShomatePoly> &mlg = m_low[grp-1];
00251       const ShomatePoly *nlow = &(mlg[pos]);
00252 
00253       doublereal tmid = nlow->maxTemp();
00254       if (t < tmid) {
00255         nlow->updateProperties(&m_t[0], cp_R, h_RT, s_R);
00256       } else {
00257         const vector<ShomatePoly> &mhg = m_high[grp-1];
00258         const ShomatePoly *nhigh = &(mhg[pos]);
00259         nhigh->updateProperties(&m_t[0], cp_R, h_RT, s_R);
00260       }
00261     }
00262 
00263     //! Compute the reference-state properties for all species.
00264     /*!
00265      * Given temperature T in K, this method updates the values of
00266      * the non-dimensional heat capacity at constant pressure,
00267      * enthalpy, and entropy, at the reference pressure, Pref
00268      * of each of the standard states.
00269      *
00270      * @param t       Temperature (Kelvin)
00271      * @param cp_R    Vector of Dimensionless heat capacities.
00272      *                (length m_kk).
00273      * @param h_RT    Vector of Dimensionless enthalpies.
00274      *                (length m_kk).
00275      * @param s_R     Vector of Dimensionless entropies.
00276      *                (length m_kk).
00277      */
00278     virtual void update(doublereal t, doublereal* cp_R, 
00279                         doublereal* h_RT, doublereal* s_R) const {
00280       int i;
00281 
00282       doublereal tt = 1.e-3*t;
00283       m_t[0] = tt;
00284       m_t[1] = tt*tt;
00285       m_t[2] = m_t[1]*tt;
00286       m_t[3] = 1.0/m_t[1];
00287       m_t[4] = log(tt);
00288       m_t[5] = 1.0/GasConstant;
00289       m_t[6] = 1.0/(GasConstant * t);
00290 
00291       vector<ShomatePoly>::const_iterator _begin, _end;
00292       for (i = 0; i != m_ngroups; i++) {
00293         if (t > m_tmid[i]) {
00294           _begin  = m_high[i].begin();
00295           _end    = m_high[i].end();
00296         }
00297         else {
00298           _begin  = m_low[i].begin();
00299           _end    = m_low[i].end();
00300         }
00301         for (; _begin != _end; ++_begin) {
00302           _begin->updateProperties(&m_t[0], cp_R, h_RT, s_R);
00303         }
00304       }
00305     }
00306 
00307     //! Minimum temperature.
00308     /*!
00309      * If no argument is supplied, this
00310      * method returns the minimum temperature for which \e all
00311      * parameterizations are valid. If an integer index k is
00312      * supplied, then the value returned is the minimum
00313      * temperature for species k in the phase.
00314      *
00315      * @param k    Species index
00316      */ 
00317     virtual doublereal minTemp(int k=-1) const {
00318       if (k < 0)
00319         return m_tlow_max;
00320       else
00321         return m_tlow[k];
00322     }
00323 
00324     //! Maximum temperature.
00325     /*!
00326      * If no argument is supplied, this
00327      * method returns the maximum temperature for which \e all
00328      * parameterizations are valid. If an integer index k is
00329      * supplied, then the value returned is the maximum
00330      * temperature for parameterization k.
00331      *
00332      * @param k  species index
00333      */
00334     virtual doublereal maxTemp(int k=-1) const {
00335       if (k < 0)
00336         return m_thigh_min;
00337       else
00338         return m_thigh[k];
00339     }
00340 
00341     //! The reference-state pressure for species k.
00342     /*!
00343      *
00344      * returns the reference state pressure in Pascals for
00345      * species k. If k is left out of the argument list,
00346      * it returns the reference state pressure for the first
00347      * species.
00348      * Note that some SpeciesThermo implementations, such
00349      * as those for ideal gases, require that all species
00350      * in the same phase have the same reference state pressures.
00351      *
00352      * @param k species index
00353      */
00354     virtual doublereal refPressure(int k=-1) const {
00355       return m_p0;
00356     }
00357 
00358     //! This utility function reports the type of parameterization
00359     //! used for the species with index number index.
00360     /*!
00361      *
00362      * @param index  Species index
00363      */
00364     virtual int reportType(int index) const { return SHOMATE; }
00365   
00366     /*!
00367      * This utility function reports back the type of 
00368      * parameterization and all of the parameters for the 
00369      * species, index.
00370      *
00371      * @param index     Species index
00372      * @param type      Integer type of the standard type
00373      * @param c         Vector of coefficients used to set the
00374      *                  parameters for the standard state.
00375      *           
00376      * @param minTemp   output - Minimum temperature
00377      * @param maxTemp   output - Maximum temperature
00378      * @param refPressure output - reference pressure (Pa).
00379      */
00380     virtual void reportParams(int index, int &type, 
00381                               doublereal * const c, 
00382                               doublereal &minTemp, 
00383                               doublereal &maxTemp, 
00384                               doublereal &refPressure) const {
00385       type = reportType(index);
00386       if (type == SHOMATE) {
00387         int grp = m_group_map[index];
00388         int pos = m_posInGroup_map[index];
00389         int itype = SHOMATE;
00390         const vector<ShomatePoly> &mlg = m_low[grp-1];
00391         const vector<ShomatePoly> &mhg = m_high[grp-1];
00392         const ShomatePoly *lowPoly  = &(mlg[pos]);
00393         const ShomatePoly *highPoly = &(mhg[pos]);
00394         doublereal tmid = lowPoly->maxTemp();
00395         c[0] = tmid;
00396         int n;
00397         double ttemp;
00398         lowPoly->reportParameters(n, itype, minTemp, ttemp, refPressure,
00399                                   c + 1);
00400         if (n != index) {
00401           throw CanteraError("  ", "confused");
00402         }
00403         if (itype != SHOMATE && itype != SHOMATE1) {
00404           throw CanteraError("  ", "confused");
00405         }
00406         highPoly->reportParameters(n, itype,  ttemp, maxTemp,
00407                                    refPressure, c + 8);
00408         if (n != index) {
00409           throw CanteraError("  ", "confused");
00410         }
00411         if (itype != SHOMATE && itype != SHOMATE1) {
00412           throw CanteraError("  ", "confused");
00413         }
00414       } else {
00415         throw CanteraError(" ", "confused");
00416       }
00417     }
00418 
00419     //! Modify parameters for the standard state
00420     /*!
00421      * @param index Species index
00422      * @param c     Vector of coefficients used to set the
00423      *              parameters for the standard state.
00424      */
00425     virtual void modifyParams(int index, doublereal *c) {
00426       int type = reportType(index);
00427       if (type == SHOMATE) {
00428         int grp = m_group_map[index];
00429         int pos = m_posInGroup_map[index];
00430         vector<ShomatePoly> &mlg = m_low[grp-1];
00431         vector<ShomatePoly> &mhg = m_high[grp-1];
00432         ShomatePoly *lowPoly  = &(mlg[pos]);
00433         ShomatePoly *highPoly = &(mhg[pos]);
00434         doublereal tmid = lowPoly->maxTemp();
00435         if (fabs(c[0] - tmid) > 0.001) {
00436           throw CanteraError("modifyParams", "can't change mid temp");
00437         }
00438 
00439         lowPoly->modifyParameters(c + 1);
00440 
00441         highPoly->modifyParameters(c + 8);
00442 
00443       } else {
00444         throw CanteraError(" ", "confused");
00445       }
00446     }
00447 
00448 #ifdef H298MODIFY_CAPABILITY
00449  
00450     virtual doublereal reportOneHf298(int k) const {
00451       doublereal h;
00452       doublereal t = 298.15;
00453 
00454       int grp = m_group_map[k];
00455       int pos = m_posInGroup_map[k];
00456       const vector<ShomatePoly> &mlg = m_low[grp-1];
00457       const ShomatePoly *nlow = &(mlg[pos]);
00458 
00459       doublereal tmid = nlow->maxTemp();
00460       if (t <= tmid) {
00461         h = nlow->reportHf298();
00462       } else {
00463         const vector<ShomatePoly> &mhg = m_high[grp-1];
00464         const ShomatePoly *nhigh = &(mhg[pos]);
00465         h = nhigh->reportHf298();
00466       }
00467       return h;
00468     }
00469 
00470     virtual void modifyOneHf298(const int k, const doublereal Hf298New) {
00471 
00472       int grp = m_group_map[k];
00473       int pos = m_posInGroup_map[k];
00474       vector<ShomatePoly> &mlg = m_low[grp-1];
00475       ShomatePoly *nlow = &(mlg[pos]);
00476       vector<ShomatePoly> &mhg = m_high[grp-1];
00477       ShomatePoly *nhigh = &(mhg[pos]);
00478       doublereal tmid = nlow->maxTemp();
00479 
00480       double hnow = reportOneHf298(k);
00481       double delH =  Hf298New - hnow;
00482       if (298.15 <= tmid) {
00483         nlow->modifyOneHf298(k, Hf298New);
00484         double h = nhigh->reportHf298(0);
00485         double hnew = h + delH;
00486         nhigh->modifyOneHf298(k, hnew);
00487       } else {
00488         nhigh->modifyOneHf298(k, Hf298New);
00489         double h = nlow->reportHf298(0);
00490         double hnew = h + delH;
00491         nlow->modifyOneHf298(k, hnew);
00492       }
00493  
00494     }
00495 
00496   
00497 #endif
00498   protected:
00499 
00500     //! Vector of vector of NasaPoly1's for the high temp region.
00501     /*!
00502      * This is the high temp region representation.
00503      * The first Length is equal to the number of groups.
00504      * The second vector is equal to the number of species
00505      * in that particular group.
00506      */
00507     vector<vector<ShomatePoly> > m_high;
00508 
00509     //! Vector of vector of NasaPoly1's for the low temp region.
00510     /*!
00511      * This is the low temp region representation.
00512      * The first Length is equal to the number of groups.
00513      * The second vector is equal to the number of species
00514      * in that particular group.
00515      */
00516     vector<vector<ShomatePoly> > m_low;
00517 
00518    //! Map between the midpoint temperature, as an int, to the group number
00519     /*!
00520      * Length is equal to the number of groups. Only used in the setup.
00521      */
00522     map<int, int>              m_index;
00523 
00524     //! Vector of log temperature limits
00525     /*!
00526      * Length is equal to the number of groups.
00527      */
00528     vector_fp                  m_tmid;
00529 
00530     //! Maximum value of the low temperature limit 
00531     doublereal                 m_tlow_max;
00532 
00533     //! Minimum value of the high temperature limit
00534     doublereal                 m_thigh_min;
00535 
00536     //! Vector of low temperature limits (species index)
00537     /*!
00538      * Length is equal to number of species
00539      */
00540     vector_fp                  m_tlow;
00541 
00542     //! Vector of low temperature limits (species index)
00543     /*!
00544      * Length is equal to number of species
00545      */
00546     vector_fp                  m_thigh;
00547 
00548     //! Reference pressure (Pa)
00549     /*!
00550      * all species must have the same reference pressure.
00551      */
00552     doublereal                 m_p0;
00553 
00554     //! number of groups
00555     int                        m_ngroups;
00556 
00557     //! Vector of temperature polynomials
00558     mutable vector_fp          m_t;
00559 
00560     /*!
00561      * This map takes as its index, the species index in the phase.
00562      * It returns the group index, where the temperature polynomials
00563      * for that species are stored. group indecises start at 1,
00564      * so a decrement is always performed to access vectors.
00565      */
00566     mutable map<int, int>              m_group_map;
00567 
00568     /*!
00569      * This map takes as its index, the species index in the phase.
00570      * It returns the position index within the group, where the 
00571      * temperature polynomials for that species are storred.
00572      */
00573     mutable map<int, int>              m_posInGroup_map;
00574   };
00575 
00576 }
00577 
00578 #endif
Generated by  doxygen 1.6.3