00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
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
00073
00074
00075 *this = b;
00076 }
00077
00078
00079
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
00094 PDSS* PDSS_SSVol::duplMyselfAsPDSS() const {
00095 PDSS_SSVol * idg = new PDSS_SSVol(*this);
00096 return (PDSS *) idg;
00097 }
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
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
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
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
00189
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
00263
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
00356 doublereal PDSS_SSVol::critTemperature() const {
00357 throw CanteraError("PDSS_SSVol::critTemperature()", "unimplemented");
00358 return (0.0);
00359 }
00360
00361
00362 doublereal PDSS_SSVol::critPressure() const {
00363 throw CanteraError("PDSS_SSVol::critPressure()", "unimplemented");
00364 return (0.0);
00365 }
00366
00367
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
00431 doublereal PDSS_SSVol::satPressure(doublereal t){
00432 return (1.0E-200);
00433 }
00434
00435 }