PDSS_SSVol.cpp

Go to the documentation of this file.
00001 /**
00002  * @file PDSS_SSVol.cpp
00003  * Implementation of a pressure dependent standard state 
00004  * virtual function.
00005  */
00006 /*
00007  * Copywrite (2006) Sandia Corporation. Under the terms of
00008  * Contract DE-AC04-94AL85000 with Sandia Corporation, the
00009  * U.S. Government retains certain rights in this software.
00010  */
00011 /*
00012  * $Id: PDSS_SSVol.cpp 279 2009-12-05 19:08:43Z hkmoffa $
00013  */
00014 
00015 #include "ct_defs.h"
00016 #include "xml.h"
00017 #include "ctml.h"
00018 #include "PDSS_SSVol.h"
00019 #include "ThermoFactory.h"
00020 
00021 #include "VPStandardStateTP.h"
00022 
00023 using namespace std;
00024 
00025 namespace Cantera {
00026   /**
00027    * Basic list of constructors and duplicators
00028    */
00029 
00030   PDSS_SSVol::PDSS_SSVol(VPStandardStateTP *tp, int spindex) :
00031     PDSS(tp, spindex), 
00032     volumeModel_(cSSVOLUME_CONSTANT),
00033     m_constMolarVolume(-1.0)
00034   {
00035     m_pdssType = cPDSS_SSVOL;
00036     TCoeff_[0] = 0.0;
00037     TCoeff_[1] = 0.0;
00038     TCoeff_[2] = 0.0;
00039   }
00040 
00041 
00042   PDSS_SSVol::PDSS_SSVol(VPStandardStateTP *tp,
00043                          int spindex, std::string inputFile, std::string id) :
00044     PDSS(tp, spindex),
00045     volumeModel_(cSSVOLUME_CONSTANT),
00046     m_constMolarVolume(-1.0)
00047   {
00048   
00049     m_pdssType = cPDSS_SSVOL;
00050     constructPDSSFile(tp, spindex, inputFile, id);
00051   }
00052 
00053   PDSS_SSVol::PDSS_SSVol(VPStandardStateTP *tp, int spindex,
00054                          const XML_Node& speciesNode, 
00055                          const XML_Node& phaseRoot, 
00056                          bool spInstalled) :
00057     PDSS(tp, spindex),
00058     volumeModel_(cSSVOLUME_CONSTANT),
00059     m_constMolarVolume(-1.0)
00060   {
00061     m_pdssType = cPDSS_SSVOL;
00062     constructPDSSXML(tp, spindex, speciesNode,  phaseRoot, spInstalled) ;
00063   }
00064 
00065 
00066   PDSS_SSVol::PDSS_SSVol(const PDSS_SSVol &b) :
00067     PDSS(b),
00068     volumeModel_(cSSVOLUME_CONSTANT),
00069     m_constMolarVolume(-1.0)
00070   {
00071     /*
00072      * Use the assignment operator to do the brunt
00073      * of the work for the copy construtor.
00074      */
00075     *this = b;
00076   }
00077 
00078   /*
00079    * Assignment operator
00080    */
00081   PDSS_SSVol& PDSS_SSVol::operator=(const PDSS_SSVol&b) {
00082     if (&b == this) return *this;
00083     PDSS::operator=(b);
00084     volumeModel_ = b.volumeModel_;
00085     m_constMolarVolume = b.m_constMolarVolume;
00086     TCoeff_ = b.TCoeff_;
00087     return *this;
00088   }
00089 
00090   PDSS_SSVol::~PDSS_SSVol() { 
00091   }
00092   
00093   //! Duplicator
00094   PDSS* PDSS_SSVol::duplMyselfAsPDSS() const {
00095     PDSS_SSVol * idg = new PDSS_SSVol(*this);
00096     return (PDSS *) idg;
00097   }
00098 
00099   /*
00100    * constructPDSSXML:
00101    *
00102    * Initialization of a PDSS_SSVol object using an
00103    * xml file.
00104    *
00105    * This routine is a precursor to initThermo(XML_Node*)
00106    * routine, which does most of the work.
00107    *
00108    * @param infile XML file containing the description of the
00109    *        phase
00110    *
00111    * @param id  Optional parameter identifying the name of the
00112    *            phase. If none is given, the first XML
00113    *            phase element will be used.
00114    */
00115   void PDSS_SSVol::constructPDSSXML(VPStandardStateTP *tp, int spindex,
00116                                        const XML_Node& speciesNode, 
00117                                        const XML_Node& phaseNode, bool spInstalled) {
00118     PDSS::initThermo();
00119     SpeciesThermo &sp = m_tp->speciesThermo();
00120     m_p0 = sp.refPressure(m_spindex);
00121 
00122     if (!spInstalled) {
00123       throw CanteraError("PDSS_SSVol::constructPDSSXML", "spInstalled false not handled");
00124     }
00125 
00126     const XML_Node *ss = speciesNode.findByName("standardState");
00127     if (!ss) {
00128       throw CanteraError("PDSS_SSVol::constructPDSSXML",
00129                          "no standardState Node for species " + speciesNode.name());
00130     }
00131     std::string model = (*ss)["model"];
00132     if (model == "constant_incompressible" || model == "constant") {
00133       volumeModel_ = cSSVOLUME_CONSTANT; 
00134       m_constMolarVolume = getFloat(*ss, "molarVolume", "toSI");
00135     } else if (model == "temperature_polynomial") {
00136       volumeModel_ = cSSVOLUME_TPOLY;
00137       int num = getFloatArray(*ss, TCoeff_, true, "", "volumeTemperaturePolynomial");
00138       if (num != 4) {
00139         throw CanteraError("PDSS_SSVol::constructPDSSXML",
00140                            " Didn't get 4 density polynomial numbers for species " + speciesNode.name());
00141       }
00142     } else if (model == "density_temperature_polynomial") {
00143       volumeModel_ = cSSVOLUME_DENSITY_TPOLY;
00144       int num = getFloatArray(*ss, TCoeff_, true, "", "densityTemperaturePolynomial");
00145       if (num != 4) {
00146         throw CanteraError("PDSS_SSVol::constructPDSSXML",
00147                            " Didn't get 4 density polynomial numbers for species " + speciesNode.name());
00148       }
00149     } else {
00150       throw CanteraError("PDSS_SSVol::constructPDSSXML",
00151                          "standardState model for species isn't constant_incompressible: " + speciesNode.name());
00152     }
00153     std::string id = "";
00154  
00155   }
00156 
00157    
00158   /*
00159    * constructPDSSFile():
00160    *
00161    * Initialization of a PDSS_SSVol object using an
00162    * xml file.
00163    *
00164    * This routine is a precursor to initThermo(XML_Node*)
00165    * routine, which does most of the work.
00166    *
00167    * @param infile XML file containing the description of the
00168    *        phase
00169    *
00170    * @param id  Optional parameter identifying the name of the
00171    *            phase. If none is given, the first XML
00172    *            phase element will be used.
00173    */
00174   void PDSS_SSVol::constructPDSSFile(VPStandardStateTP *tp, int spindex,
00175                                         std::string inputFile, std::string id) {
00176 
00177     if (inputFile.size() == 0) {
00178       throw CanteraError("PDSS_SSVol::initThermo",
00179                          "input file is null");
00180     }
00181     std::string path = findInputFile(inputFile);
00182     ifstream fin(path.c_str());
00183     if (!fin) {
00184       throw CanteraError("PDSS_SSVol::initThermo","could not open "
00185                          +path+" for reading.");
00186     }
00187     /*
00188      * The phase object automatically constructs an XML object.
00189      * Use this object to store information.
00190      */
00191 
00192     XML_Node *fxml = new XML_Node();
00193     fxml->build(fin);
00194     XML_Node *fxml_phase = findXMLPhase(fxml, id);
00195     if (!fxml_phase) {
00196       throw CanteraError("PDSS_SSVol::initThermo",
00197                          "ERROR: Can not find phase named " +
00198                          id + " in file named " + inputFile);
00199     }
00200 
00201     XML_Node& speciesList = fxml_phase->child("speciesArray");
00202     XML_Node* speciesDB = get_XML_NameID("speciesData", speciesList["datasrc"],
00203                                          &(fxml_phase->root()));
00204     const vector<string>&sss = tp->speciesNames();
00205     const XML_Node* s =  speciesDB->findByAttr("name", sss[spindex]);
00206 
00207     constructPDSSXML(tp, spindex, *s, *fxml_phase, true);
00208     delete fxml;
00209   }
00210 
00211   void PDSS_SSVol::initThermoXML(const XML_Node& phaseNode, std::string& id) {
00212     PDSS::initThermoXML(phaseNode, id);
00213     m_minTemp = m_spthermo->minTemp(m_spindex);
00214     m_maxTemp = m_spthermo->maxTemp(m_spindex);
00215     m_p0 = m_spthermo->refPressure(m_spindex);
00216     m_mw = m_tp->molecularWeight(m_spindex);
00217   }
00218 
00219   void PDSS_SSVol::initThermo() {
00220     PDSS::initThermo();
00221     SpeciesThermo &sp = m_tp->speciesThermo();
00222     m_p0 = sp.refPressure(m_spindex);
00223     m_V0_ptr[m_spindex] = m_constMolarVolume;
00224     m_Vss_ptr[m_spindex] = m_constMolarVolume;
00225   }
00226 
00227   doublereal 
00228   PDSS_SSVol::enthalpy_mole() const {
00229     doublereal val = enthalpy_RT();
00230     doublereal RT = GasConstant * m_temp;
00231     return (val * RT);
00232   }
00233 
00234   doublereal 
00235   PDSS_SSVol::enthalpy_RT() const {
00236     doublereal val = m_hss_RT_ptr[m_spindex];
00237     return (val);
00238   }
00239 
00240   doublereal 
00241   PDSS_SSVol::intEnergy_mole() const {
00242     doublereal pVRT = (m_pres * m_Vss_ptr[m_spindex]) / (GasConstant * m_temp);
00243     doublereal val = m_h0_RT_ptr[m_spindex] - pVRT;
00244     doublereal RT = GasConstant * m_temp;
00245     return (val * RT);
00246   }
00247 
00248 
00249   doublereal
00250   PDSS_SSVol::entropy_mole() const {
00251     doublereal val = entropy_R();
00252     return (val * GasConstant);
00253   }
00254 
00255   doublereal
00256   PDSS_SSVol::entropy_R() const {
00257     doublereal val = m_sss_R_ptr[m_spindex];
00258     return (val);
00259   }
00260 
00261   /**
00262    * Calculate the Gibbs free energy in mks units of
00263    * J kmol-1 K-1.
00264    */
00265   doublereal
00266   PDSS_SSVol::gibbs_mole() const {
00267     doublereal val = gibbs_RT();
00268     doublereal RT = GasConstant * m_temp;
00269     return (val * RT);
00270   }
00271 
00272   doublereal
00273   PDSS_SSVol::gibbs_RT() const {
00274     doublereal val = m_gss_RT_ptr[m_spindex];
00275     return (val);
00276   }
00277 
00278   doublereal 
00279   PDSS_SSVol::cp_mole() const {
00280     doublereal val = m_cpss_R_ptr[m_spindex];
00281     return (val * GasConstant);
00282   }
00283 
00284   doublereal 
00285   PDSS_SSVol::cp_R() const {
00286     doublereal val = m_cpss_R_ptr[m_spindex];
00287     return (val);
00288   }
00289 
00290   doublereal 
00291   PDSS_SSVol::cv_mole() const {
00292     doublereal val = (cp_mole() -  m_V0_ptr[m_spindex]);
00293     return (val);
00294   }
00295 
00296   doublereal 
00297   PDSS_SSVol::molarVolume() const {
00298     doublereal val = m_Vss_ptr[m_spindex];
00299     return (val);
00300   }
00301 
00302   doublereal 
00303   PDSS_SSVol::density() const {
00304     doublereal val = m_Vss_ptr[m_spindex];
00305     return (m_mw/val);
00306   }
00307 
00308   doublereal
00309   PDSS_SSVol::gibbs_RT_ref() const {
00310     doublereal val = m_g0_RT_ptr[m_spindex];
00311     return (val);
00312   }
00313 
00314   doublereal PDSS_SSVol::enthalpy_RT_ref() const {
00315     doublereal val = m_h0_RT_ptr[m_spindex];
00316     return (val);
00317   }
00318 
00319   doublereal PDSS_SSVol::entropy_R_ref() const {
00320     doublereal val = m_s0_R_ptr[m_spindex];
00321     return (val);
00322   }
00323 
00324   doublereal PDSS_SSVol::cp_R_ref() const {
00325     doublereal val = m_cp0_R_ptr[m_spindex];
00326     return (val);
00327   }
00328 
00329   doublereal PDSS_SSVol::molarVolume_ref() const {
00330     doublereal val = m_V0_ptr[m_spindex];
00331     return (val);
00332   }
00333 
00334   void PDSS_SSVol::calcMolarVolume() const {
00335     if (volumeModel_ == cSSVOLUME_CONSTANT ) {
00336       m_Vss_ptr[m_spindex] = m_constMolarVolume;
00337     } else if (volumeModel_ == cSSVOLUME_TPOLY) {
00338       m_Vss_ptr[m_spindex] = TCoeff_[0] + m_temp * (TCoeff_[1] + m_temp * (TCoeff_[2] + m_temp * TCoeff_[3]));
00339       dVdT_   = TCoeff_[1] + 2.0 * m_temp * TCoeff_[2] + 3.0 * m_temp * m_temp * TCoeff_[3];
00340       d2VdT2_ =  2.0 * TCoeff_[2] + 6.0 * m_temp * TCoeff_[3];
00341     } else  if (volumeModel_ == cSSVOLUME_DENSITY_TPOLY) {
00342       doublereal dens =  TCoeff_[0] + m_temp * (TCoeff_[1] + m_temp * (TCoeff_[2] + m_temp * TCoeff_[3]));
00343       m_Vss_ptr[m_spindex] = m_mw / dens;
00344       doublereal dens2 = dens * dens;
00345       doublereal ddensdT =  TCoeff_[1] + 2.0 * m_temp * TCoeff_[2] + 3.0 * m_temp * m_temp * TCoeff_[3];
00346       doublereal d2densdT2 = 2.0 * TCoeff_[2] + 6.0 * m_temp * TCoeff_[3];
00347       dVdT_   = - m_mw / (dens2) * (ddensdT);
00348       d2VdT2_ = 2.0 * m_mw / (dens2 * dens) * ddensdT * ddensdT - m_mw / dens2 * d2densdT2; 
00349     } else {
00350       throw CanteraError("PDSS_SSVol::calcMolarVolume", "unimplemented");
00351     }
00352   }
00353  
00354 
00355   /// critical temperature 
00356   doublereal PDSS_SSVol::critTemperature() const { 
00357     throw CanteraError("PDSS_SSVol::critTemperature()", "unimplemented");
00358     return (0.0);
00359   }
00360         
00361   /// critical pressure
00362   doublereal PDSS_SSVol::critPressure() const {
00363     throw CanteraError("PDSS_SSVol::critPressure()", "unimplemented");
00364     return (0.0);
00365   }
00366         
00367   /// critical density
00368   doublereal PDSS_SSVol::critDensity() const {
00369     throw CanteraError("PDSS_SSVol::critDensity()", "unimplemented");
00370     return (0.0);
00371   }
00372 
00373 
00374 
00375   void PDSS_SSVol::setPressure(doublereal p) {
00376     m_pres = p;
00377     doublereal deltaP = m_pres - m_p0;
00378     if (fabs(deltaP) < 1.0E-10) {
00379       m_hss_RT_ptr[m_spindex] = m_h0_RT_ptr[m_spindex];
00380       m_sss_R_ptr[m_spindex] = m_s0_R_ptr[m_spindex];
00381       m_gss_RT_ptr[m_spindex] = m_hss_RT_ptr[m_spindex] - m_sss_R_ptr[m_spindex];
00382       m_cpss_R_ptr[m_spindex] = m_cp0_R_ptr[m_spindex];
00383     } else {
00384       doublereal del_pRT = deltaP / (GasConstant * m_temp);
00385       doublereal sV_term =  - deltaP / (GasConstant) * dVdT_;
00386       m_hss_RT_ptr[m_spindex] = m_h0_RT_ptr[m_spindex] + sV_term + del_pRT * (m_Vss_ptr[m_spindex]);
00387       m_sss_R_ptr[m_spindex] = m_s0_R_ptr[m_spindex] + sV_term;
00388       m_gss_RT_ptr[m_spindex] = m_hss_RT_ptr[m_spindex] - m_sss_R_ptr[m_spindex];
00389       m_cpss_R_ptr[m_spindex] = m_cp0_R_ptr[m_spindex] - m_temp * deltaP * d2VdT2_;
00390     }
00391   }    
00392 
00393   void PDSS_SSVol::setTemperature(doublereal temp) {
00394     m_temp = temp;
00395     m_spthermo->update_one(m_spindex, temp, m_cp0_R_ptr, m_h0_RT_ptr, m_s0_R_ptr);
00396     calcMolarVolume();
00397     m_g0_RT_ptr[m_spindex] =  m_h0_RT_ptr[m_spindex] -  m_s0_R_ptr[m_spindex];
00398     doublereal deltaP = m_pres - m_p0;
00399     if (fabs(deltaP) < 1.0E-10) {
00400       m_hss_RT_ptr[m_spindex] = m_h0_RT_ptr[m_spindex];
00401       m_sss_R_ptr[m_spindex] = m_s0_R_ptr[m_spindex];
00402       m_gss_RT_ptr[m_spindex] = m_hss_RT_ptr[m_spindex] - m_sss_R_ptr[m_spindex];
00403       m_cpss_R_ptr[m_spindex] = m_cp0_R_ptr[m_spindex];
00404     } else {
00405       doublereal del_pRT = deltaP / (GasConstant * m_temp);
00406       doublereal sV_term =  - deltaP / (GasConstant) * dVdT_;
00407       m_hss_RT_ptr[m_spindex] = m_h0_RT_ptr[m_spindex] + sV_term + del_pRT * (m_Vss_ptr[m_spindex]);
00408       m_sss_R_ptr[m_spindex] = m_s0_R_ptr[m_spindex] + sV_term;
00409       m_gss_RT_ptr[m_spindex] = m_hss_RT_ptr[m_spindex] - m_sss_R_ptr[m_spindex];
00410       m_cpss_R_ptr[m_spindex] = m_cp0_R_ptr[m_spindex] - m_temp * deltaP * d2VdT2_;
00411     }    
00412   }
00413 
00414 
00415   void PDSS_SSVol::setState_TP(doublereal temp, doublereal pres) {
00416     m_pres = pres;
00417     setTemperature(temp);
00418   }
00419 
00420 
00421   void PDSS_SSVol::setState_TR(doublereal temp, doublereal rho) {
00422     doublereal rhoStored = m_mw / m_constMolarVolume;
00423     if (fabs(rhoStored - rho) / (rhoStored + rho) > 1.0E-4) {
00424       throw CanteraError("PDSS_SSVol::setState_TR",
00425                          "Inconsistent supplied rho");
00426     }
00427     setTemperature(temp);
00428   }
00429 
00430   /// saturation pressure
00431   doublereal PDSS_SSVol::satPressure(doublereal t){
00432     return (1.0E-200);
00433   }
00434  
00435 }
Generated by  doxygen 1.6.3