00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifdef WIN32
00018 #pragma warning(disable:4786)
00019 #endif
00020
00021
00022 #include "SpeciesThermo.h"
00023
00024
00025 #include "VPSSMgr.h"
00026 #include "VPSSMgrFactory.h"
00027
00028 #include "VPStandardStateTP.h"
00029
00030 #include "VPSSMgr_IdealGas.h"
00031 #include "VPSSMgr_ConstVol.h"
00032 #include "VPSSMgr_Water_ConstVol.h"
00033 #include "VPSSMgr_Water_HKFT.h"
00034 #include "VPSSMgr_General.h"
00035
00036 #include "VPSSMgr_types.h"
00037
00038 #include "SpeciesThermoMgr.h"
00039 #include "speciesThermoTypes.h"
00040 #include "SpeciesThermo.h"
00041 #include "SpeciesThermoFactory.h"
00042 #include "GeneralSpeciesThermo.h"
00043
00044 #include "mix_defs.h"
00045
00046 #include "xml.h"
00047 #include "ctml.h"
00048
00049 using namespace ctml;
00050 using namespace std;
00051
00052
00053 namespace Cantera {
00054
00055 VPSSMgrFactory* VPSSMgrFactory::s_factory = 0;
00056
00057 #if defined(THREAD_SAFE_CANTERA)
00058
00059
00060 boost::mutex VPSSMgrFactory::vpss_species_thermo_mutex;
00061 #endif
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 static void getVPSSMgrTypes(std::vector<XML_Node *> & spDataNodeList,
00075 int &has_nasa_idealGas,
00076 int &has_nasa_constVol,
00077 int& has_shomate_idealGas,
00078 int& has_shomate_constVol,
00079 int& has_simple_idealGas,
00080 int& has_simple_constVol,
00081 int &has_water,
00082 int &has_tpx,
00083 int &has_hptx,
00084 int &has_other) {
00085
00086 XML_Node *ss_ptr = 0;
00087 string ssModel = "idealGas";
00088 size_t ns = spDataNodeList.size();
00089 for (size_t n = 0; n < ns; n++) {
00090 bool ifound = false;
00091 XML_Node* spNode = spDataNodeList[n];
00092 if (spNode->hasChild("standardState")) {
00093 const XML_Node& ssN = spNode->child("standardState");
00094 string mm = ssN["model"];
00095 if (mm == "waterIAPWS" || mm == "waterPDSS") {
00096 has_water++;
00097 ifound = true;
00098 }
00099 if (mm == "HKFT") {
00100 has_hptx++;
00101 ifound = true;
00102 }
00103 }
00104 if (!ifound) {
00105 if (spNode->hasChild("thermo")) {
00106 const XML_Node& th = spNode->child("thermo");
00107 if (spNode->hasChild("standardState")) {
00108 ss_ptr = &(spNode->child("standardState"));
00109 ssModel = ss_ptr->attrib("model");
00110 }
00111 if (th.hasChild("NASA")) {
00112 if (ssModel == "idealGas") {
00113 has_nasa_idealGas++;
00114 } else if (ssModel == "constant_incompressible" ||
00115 ssModel == "constantVolume") {
00116 has_nasa_constVol++;
00117 } else if (ssModel == "temperature_polynomial" ||
00118 ssModel == "density_temperature_polynomial" ||
00119 ssModel == "constant") {
00120 has_other++;
00121 } else {
00122 throw UnknownVPSSMgrModel("getVPSSMgrTypes:",
00123 spNode->attrib("name"));
00124 }
00125 ifound = true;
00126 }
00127 if (th.hasChild("Shomate")) {
00128 if (ssModel == "idealGas") {
00129 has_shomate_idealGas++;
00130 } else if (ssModel == "constant_incompressible" ||
00131 ssModel == "constantVolume") {
00132 has_shomate_constVol++;
00133 } else if (ssModel == "temperature_polynomial" ||
00134 ssModel == "density_temperature_polynomial" ||
00135 ssModel == "constant") {
00136 has_other++;
00137 } else {
00138 throw UnknownVPSSMgrModel("getVPSSMgrTypes:",
00139 spNode->attrib("name"));
00140 }
00141 ifound = true;
00142 }
00143 if (th.hasChild("const_cp")){
00144 if (ssModel == "idealGas") {
00145 has_simple_idealGas++;
00146 } else if (ssModel == "constant_incompressible" ||
00147 ssModel == "constantVolume") {
00148 has_simple_constVol++;
00149 } else if (ssModel == "temperature_polynomial" ||
00150 ssModel == "density_temperature_polynomial" ||
00151 ssModel == "constant") {
00152 has_other++;
00153 } else {
00154 throw UnknownVPSSMgrModel("getVPSSMgrTypes:",
00155 spNode->attrib("name"));
00156 }
00157 ifound = true;
00158 }
00159 if (th.hasChild("poly")) {
00160 if (th.child("poly")["order"] == "1") {
00161 has_simple_constVol = 1;
00162 ifound = true;
00163 } else throw CanteraError("newSpeciesThermo",
00164 "poly with order > 1 not yet supported");
00165 }
00166 if (th.hasChild("Mu0")) {
00167 has_other++;
00168 ifound = true;
00169 }
00170 if (th.hasChild("NASA9")) {
00171 has_other++;
00172 ifound = true;
00173 }
00174 if (th.hasChild("NASA9MULTITEMP")) {
00175 has_other++;
00176 ifound = true;
00177 }
00178 if (th.hasChild("adsorbate")) {
00179 has_other++;
00180 ifound = true;
00181 }
00182 if (th.hasChild("HKFT")) {
00183 has_hptx++;
00184 ifound = true;
00185 }
00186 } else {
00187 throw UnknownVPSSMgrModel("getVPSSMgrTypes:",
00188 spNode->attrib("name"));
00189 }
00190 }
00191 }
00192 }
00193
00194
00195
00196
00197
00198
00199
00200 void VPSSMgrFactory::deleteFactory() {
00201
00202 #if defined(THREAD_SAFE_CANTERA)
00203 boost::mutex::scoped_lock lock(species_thermo_mutex);
00204 #endif
00205 if (s_factory) {
00206 delete s_factory;
00207 s_factory = 0;
00208 }
00209 }
00210
00211 VPSSMgrFactory::~VPSSMgrFactory() {
00212 }
00213
00214 VPSSMgr_enumType
00215 VPSSMgrFactory::VPSSMgr_StringConversion(std::string ssModel) const {
00216 std::string lssModel = lowercase(ssModel);
00217 VPSSMgr_enumType type;
00218 if (lssModel == "idealgas") {
00219 type = cVPSSMGR_IDEALGAS;
00220 } else if (lssModel == "constvol") {
00221 type = cVPSSMGR_CONSTVOL;
00222 } else if (lssModel == "purefuild") {
00223 type = cVPSSMGR_PUREFLUID;
00224 } else if (lssModel == "water_constvol") {
00225 type = cVPSSMGR_WATER_CONSTVOL;
00226 } else if (lssModel == "water_hkft") {
00227 type = cVPSSMGR_WATER_HKFT;
00228 } else if (lssModel == "general") {
00229 type = cVPSSMGR_GENERAL;
00230 } else {
00231 type = cVPSSMGR_UNDEF;
00232 }
00233 return type;
00234 }
00235
00236
00237
00238 VPSSMgr*
00239 VPSSMgrFactory::newVPSSMgr(VPStandardStateTP *vp_ptr,
00240 XML_Node* phaseNode_ptr,
00241 std::vector<XML_Node*> & spDataNodeList) {
00242
00243 std::string ssManager="";
00244 std::string vpssManager="";
00245 VPSSMgr *vpss = 0;
00246
00247
00248
00249
00250 if (phaseNode_ptr) {
00251 if (phaseNode_ptr->hasChild("thermo")) {
00252 const XML_Node& thermoNode = phaseNode_ptr->child("thermo");
00253 if (thermoNode.hasChild("standardStateManager")) {
00254 const XML_Node& ssNode = thermoNode.child("standardStateManager");
00255 ssManager = ssNode["model"];
00256 }
00257 if (thermoNode.hasChild("variablePressureStandardStateManager")) {
00258 const XML_Node& vpssNode = thermoNode.child("variablePressureStandardStateManager");
00259 vpssManager = vpssNode["model"];
00260 }
00261 }
00262 }
00263
00264
00265
00266 SpeciesThermo *spth = 0;
00267 if (ssManager != "") {
00268 spth = newSpeciesThermoMgr(ssManager);
00269 } else {
00270 spth = newSpeciesThermoMgr(spDataNodeList);
00271 }
00272 vp_ptr->setSpeciesThermo(spth);
00273
00274
00275
00276 if (vpssManager != "") {
00277 VPSSMgr_enumType type = VPSSMgr_StringConversion(vpssManager);
00278 vpss = newVPSSMgr(type, vp_ptr);
00279 return vpss;
00280 }
00281
00282
00283
00284
00285 bool haveSomeUnknowns = true;
00286 GeneralSpeciesThermo *ttmp = dynamic_cast<GeneralSpeciesThermo *>(spth);
00287 if (ttmp == 0) {
00288 haveSomeUnknowns = false;
00289 }
00290
00291
00292 if (vp_ptr->eosType() == cVPSS_IdealGas) {
00293 vpss = new VPSSMgr_IdealGas(vp_ptr, spth);
00294 return vpss;
00295 } else if (vp_ptr->eosType() == cVPSS_ConstVol) {
00296 vpss = new VPSSMgr_ConstVol(vp_ptr, spth);
00297 return vpss;
00298 }
00299
00300
00301 int inasaIG = 0, inasaCV = 0, ishomateIG = 0, ishomateCV = 0,
00302 isimpleIG = 0, isimpleCV = 0,
00303 iwater = 0, itpx = 0, iother = 0;
00304 int ihptx = 0;
00305
00306 try {
00307 getVPSSMgrTypes(spDataNodeList, inasaIG, inasaCV, ishomateIG, ishomateCV,
00308 isimpleIG, isimpleCV, iwater, itpx, ihptx, iother);
00309 } catch (UnknownSpeciesThermoModel) {
00310 iother = 1;
00311 popError();
00312 }
00313
00314 if (iwater == 1) {
00315 if (ihptx == 0) {
00316 if (inasaIG || ishomateIG || isimpleIG) {
00317 throw CanteraError("newVPSSMgr", "Ideal gas with liquid water");
00318 } else {
00319 vpss = new VPSSMgr_Water_ConstVol(vp_ptr, spth);
00320 }
00321 } else {
00322 if (inasaIG || ishomateIG || isimpleIG) {
00323 throw CanteraError("newVPSSMgr", "Ideal gas with liquid water");
00324 } else if (inasaCV || ishomateCV || isimpleCV) {
00325 vpss = new VPSSMgr_General(vp_ptr, spth);
00326 } else {
00327 vpss = new VPSSMgr_Water_HKFT(vp_ptr, spth);
00328 }
00329 }
00330 }
00331 if (vpss == 0) {
00332 if (inasaCV || ishomateCV || isimpleCV) {
00333 if (!inasaIG && !ishomateIG && !isimpleIG && !itpx && !ihptx && !iother) {
00334 vpss = new VPSSMgr_ConstVol(vp_ptr, spth);
00335 }
00336 }
00337 }
00338 if (vpss == 0) {
00339 vpss = new VPSSMgr_General(vp_ptr, spth);
00340 }
00341 return vpss;
00342 }
00343
00344
00345
00346
00347
00348 VPSSMgr*
00349 VPSSMgrFactory::newVPSSMgr(VPSSMgr_enumType type, VPStandardStateTP *vp_ptr) {
00350 SpeciesThermo &spthermoRef = vp_ptr->speciesThermo();
00351 switch (type) {
00352 case cVPSSMGR_IDEALGAS:
00353 return new VPSSMgr_IdealGas(vp_ptr, &spthermoRef);
00354 case cVPSSMGR_CONSTVOL:
00355 return new VPSSMgr_ConstVol(vp_ptr, &spthermoRef);
00356 case cVPSSMGR_PUREFLUID:
00357 throw CanteraError("VPSSMgrFactory::newVPSSMgr",
00358 "unimplemented");
00359 case cVPSSMGR_WATER_CONSTVOL:
00360 return new VPSSMgr_Water_ConstVol(vp_ptr, &spthermoRef);
00361 case cVPSSMGR_WATER_HKFT:
00362 return new VPSSMgr_Water_HKFT(vp_ptr, &spthermoRef);
00363 case cVPSSMGR_GENERAL:
00364 return new VPSSMgr_General(vp_ptr, &spthermoRef);
00365 case cVPSSMGR_UNDEF:
00366 default:
00367 throw UnknownVPSSMgrModel("VPSSMgrFactory::newVPSSMgr", int2str(type));
00368 return 0;
00369 }
00370 }
00371
00372
00373 VPSSMgr* newVPSSMgr(VPSSMgr_enumType type, VPStandardStateTP *vp_ptr,
00374 Cantera::VPSSMgrFactory* f) {
00375 if (f == 0) {
00376 f = VPSSMgrFactory::factory();
00377 }
00378 VPSSMgr* vpsssptherm = f->newVPSSMgr(type, vp_ptr);
00379 return vpsssptherm;
00380 }
00381
00382
00383 VPSSMgr* newVPSSMgr(VPStandardStateTP *tp_ptr,
00384 XML_Node* phaseNode_ptr,
00385 std::vector<XML_Node *> & spDataNodeList,
00386 VPSSMgrFactory* f) {
00387 if (f == 0) {
00388 f = VPSSMgrFactory::factory();
00389 }
00390 VPSSMgr* vpsssptherm = f->newVPSSMgr(tp_ptr, phaseNode_ptr, spDataNodeList);
00391 return vpsssptherm;
00392 }
00393
00394
00395 }