VPSSMgrFactory.cpp

Go to the documentation of this file.
00001 /**
00002  *  @file VPSSMgrFactory.cpp
00003  *    Definitions for factory to build instances of classes that manage the
00004  *    calculation of standard state properties for all the species in a phase
00005  *    (see \ref spthermo and class 
00006  *    \link Cantera::VPSSMgrFactory VPSSMgrFactory\endlink);
00007  */
00008 /*
00009  * $Id: VPSSMgrFactory.cpp 398 2010-02-09 20:24:11Z hkmoffa $
00010  */
00011 
00012 /*
00013  * Copywrite (2005) Sandia Corporation. Under the terms of 
00014  * Contract DE-AC04-94AL85000 with Sandia Corporation, the
00015  * U.S. Government retains certain rights in this software.
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   // Defn of the static mutex variable that locks the 
00059   // %VPSSMgr factory singelton
00060   boost::mutex VPSSMgrFactory::vpss_species_thermo_mutex;
00061 #endif
00062  
00063   /*
00064    * Examine the types of species thermo parameterizations,
00065    * and return a flag indicating the type of parameterization
00066    * needed by the species.
00067    * 
00068    *  @param spData_node Species Data XML node. This node contains a list
00069    *                     of species XML nodes underneath it.
00070    * 
00071    * @todo Make sure that spDadta_node is species Data XML node by checking 
00072    *      its name is speciesData
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   // Delete static instance of this class
00195   /*
00196    * If it is necessary to explicitly delete the factory before
00197    * the process terminates (for example, when checking for
00198    * memory leaks) then this method can be called to delete it.
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   // Chose the variable pressure standard state manager 
00237   // and the reference standard state manager
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     // First look for any explicit instructions within the XML Database
00248     // for the standard state manager and the variable pressure 
00249     // standard state manager
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     // first get the reference state handler. If we have explicit instructions,
00265     // use them to spawn the object.
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     // Next, if we have specific directions, use them to get the VPSSSMgr object
00275     // and return immediately
00276     if (vpssManager != "") {
00277       VPSSMgr_enumType type = VPSSMgr_StringConversion(vpssManager);
00278       vpss = newVPSSMgr(type, vp_ptr);
00279       return vpss;
00280     }
00281 
00282  
00283     // If it comes back as general, then there may be some unknown 
00284     // parameterizations to the SpeciesThermo factory routine.
00285     bool haveSomeUnknowns = true;
00286     GeneralSpeciesThermo *ttmp = dynamic_cast<GeneralSpeciesThermo *>(spth);
00287     if (ttmp == 0) {
00288       haveSomeUnknowns = false;
00289     }
00290  
00291     // Handle special cases based on the VPStandardState types
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   // I don't think this is currently used. However, this is a virtual 
00347   // function where additional capabilities may be added.
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   // I don't think this is currently used
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 }
Generated by  doxygen 1.6.3