00001 /** 00002 * @file ThermoFactory.h 00003 * Headers for the factory class that can create known %ThermoPhase objects 00004 * (see \ref thermoprops and class \link Cantera::ThermoFactory ThermoFactory\endlink). 00005 * 00006 */ 00007 00008 /* 00009 * $Author: hkmoffa $ 00010 * $Revision: 304 $ 00011 * $Date: 2009-12-08 12:36:40 -0500 (Tue, 08 Dec 2009) $ 00012 */ 00013 00014 // Copyright 2001 California Institute of Technology 00015 00016 00017 #ifndef THERMO_FACTORY_H 00018 #define THERMO_FACTORY_H 00019 00020 #include "ThermoPhase.h" 00021 #include "xml.h" 00022 00023 #if defined(THREAD_SAFE_CANTERA) 00024 #include <boost/thread/mutex.hpp> 00025 #endif 00026 00027 #include "FactoryBase.h" 00028 00029 namespace Cantera { 00030 00031 class SpeciesThermoFactory; 00032 class VPSSMgr; 00033 00034 /*! 00035 * @addtogroup thermoprops 00036 * 00037 * Standard %ThermoPhase objects may be instantiated by calling 00038 * the main %Cantera factory class for %ThermoPhase objects; This class is called ThermoFactory. 00039 */ 00040 //@{ 00041 00042 //! Specific error to be thrown if the type of Thermo mananger is unrecognized. 00043 /*! 00044 * This particular error class may be caught, if the application may have other 00045 * models that the main Cantera appliation doesn't know about. 00046 */ 00047 class UnknownThermoPhaseModel : public CanteraError { 00048 public: 00049 //! Constructor 00050 /*! 00051 * @param proc Function name where the error occurred. 00052 * @param thermoModel Sting name of ThermoPhase which didn't match 00053 */ 00054 UnknownThermoPhaseModel(std::string proc, std::string thermoModel) : 00055 CanteraError(proc, "Specified ThermoPhase model " 00056 + thermoModel + 00057 " does not match any known type.") {} 00058 //! destructor 00059 virtual ~UnknownThermoPhaseModel() throw() {} 00060 }; 00061 00062 00063 //! Factory class for thermodynamic property managers. 00064 /*! 00065 * This class keeps a list of the known ThermoPhase classes, and is 00066 * used to create new instances of these classes. 00067 */ 00068 class ThermoFactory : public FactoryBase { 00069 00070 public: 00071 00072 //! Static function that creates a static instance of the factory. 00073 static ThermoFactory* factory() { 00074 #if defined(THREAD_SAFE_CANTERA) 00075 boost::mutex::scoped_lock lock(thermo_mutex); 00076 #endif 00077 if (!s_factory) s_factory = new ThermoFactory; 00078 return s_factory; 00079 } 00080 00081 //! delete the static instance of this factory 00082 virtual void deleteFactory() { 00083 #if defined(THREAD_SAFE_CANTERA) 00084 boost::mutex::scoped_lock lock(thermo_mutex); 00085 #endif 00086 if (s_factory) { 00087 delete s_factory; 00088 s_factory = 0; 00089 } 00090 } 00091 00092 //! Destructor doesn't do anything. 00093 /*! 00094 * We do not delete statically created single instance of this 00095 * class here, because it would create an infinite loop if 00096 * destructor is called for that single instance. 00097 */ 00098 virtual ~ThermoFactory() { } 00099 00100 //! Create a new thermodynamic property manager. 00101 /*! 00102 * @param model String to look up the model against 00103 * 00104 * @return 00105 * Returns a pointer to a new ThermoPhase instance matching the 00106 * model string. Returns NULL if something went wrong. 00107 * Throws an exception UnknownThermoPhaseModel if the string 00108 * wasn't matched. 00109 */ 00110 virtual ThermoPhase* newThermoPhase(std::string model); 00111 00112 private: 00113 //! static member of a single instance 00114 static ThermoFactory* s_factory; 00115 00116 //! Private constructors prevents usage 00117 ThermoFactory(){}; 00118 00119 00120 #if defined(THREAD_SAFE_CANTERA) 00121 //! Decl for locking mutex for thermo factory singelton 00122 static boost::mutex thermo_mutex; 00123 #endif 00124 00125 }; 00126 00127 //! Create a new thermo manager instance. 00128 /*! 00129 * @param model String to look up the model against 00130 * @param f ThermoFactor instance to use in matching the string 00131 * 00132 * @return 00133 * Returns a pointer to a new ThermoPhase instance matching the 00134 * model string. Returns NULL if something went wrong. 00135 * Throws an exception UnknownThermoPhaseModel if the string 00136 * wasn't matched. 00137 */ 00138 inline ThermoPhase* newThermoPhase(std::string model, 00139 ThermoFactory* f=0) { 00140 if (f == 0) { 00141 f = ThermoFactory::factory(); 00142 } 00143 return f->newThermoPhase(model); 00144 } 00145 00146 //! Translate the eosType id into a string 00147 /*! 00148 * Returns a string representation of the eosType id for a phase. 00149 * @param ieos eosType id of the phase. This is unique for the phase 00150 * @param length maximum length of the return string. Defaults to 100 00151 * 00152 * @return returns a string representation. 00153 */ 00154 std::string eosTypeString(int ieos, int length = 100); 00155 00156 00157 /*! 00158 * This routine first looks up the 00159 * identity of the model for the solution thermodynamics in the 00160 * model attribute of the thermo child of the xml phase 00161 * node. Then, it does a string lookup using Cantera's internal ThermoPhase Factory routines 00162 * on the model to figure out 00163 * what ThermoPhase derived class should be assigned. It creates a new 00164 * instance of that class, and then calls importPhase() to 00165 * populate that class with the correct parameters from the XML 00166 * tree. 00167 * 00168 * @param phase XML_Node reference pointing to the phase XML element. 00169 * 00170 * @return 00171 * Returns a pointer to the completed and initialized ThermoPhase object. 00172 * 00173 * @ingroup inputfiles 00174 */ 00175 ThermoPhase* newPhase(XML_Node& phase); 00176 00177 //! Create and Initialize a ThermoPhase object from an XML input file. 00178 /*! 00179 * This routine is a wrapper around the newPhase(XML_Node) routine 00180 * which does the work. The wrapper locates the input phase XML_Node 00181 * in a file, and then instantiates the object, returning the pointer 00182 * to the ThermoPhase object. 00183 * 00184 * @param infile name of the input file 00185 * @param id name of the phase id in the file. 00186 * If this is blank, the first phase in the file is used. 00187 * 00188 * @return 00189 * Returns an initialized ThermoPhase object. 00190 */ 00191 ThermoPhase* newPhase(std::string infile, std::string id); 00192 00193 //! Import a phase information into an empty thermophase object 00194 /*! 00195 * Here we read an XML description of the thermodynamic information 00196 * for a phase. At the end of this routine, the phase should 00197 * be ready to be used within applications. This routine contains 00198 * some key routines that are used as pass back routines so that 00199 * the phase (and the contents of the XML file) may contain 00200 * variable paramerizations for the specification of the 00201 * species standard states, the equation of state, and the 00202 * specification of other nonidealities. Below, a description 00203 * is presented of the main algorithm for bringing up a %ThermoPhase 00204 * object, with care to present points where customizations 00205 * occur. 00206 * 00207 * Before invoking this routine, either the ThermoPhase Factory routines 00208 * are called or direct constructor routines are called that 00209 * instantiate an inherited ThermoPhase object. This object is input 00210 * to this routine, and therefore contains inherited routines that 00211 * drive the custimation of the initialization process. 00212 * 00213 * At the start of the routine, we import descriptions of the elements 00214 * that make up the species in a phase. 00215 * 00216 * We call setParametersFromXML(eos) to read parameters about 00217 * the thermo phase before the species are read in. 00218 * 00219 * We call addElementsFromXML() to add elements into the 00220 * description of the phase. 00221 * 00222 * We create a new species thermo manager. Function 00223 * 'newSpeciesThermoMgr' looks at the species in the database 00224 * to see what thermodynamic property parameterizations are 00225 * used, and selects a class that can handle the 00226 * parameterizations found. 00227 * 00228 * We import information about the species, including their 00229 * reference state thermodynamic polynomials. We then freeze 00230 * the state of the species in the element. 00231 * 00232 * Finally, we call initThermoXML(), 00233 * a member function of the ThermoPhase object, to "finish" 00234 * the description. Now that the species are known, 00235 * additional information may be read in about the thermodynamics 00236 * of the phase, (e.g., virial coefficients, which are 00237 * binary or ternary interaction parameters between species). 00238 * 00239 * @param phase This object must be the phase node of a 00240 * complete XML tree 00241 * description of the phase, including all of the 00242 * species data. In other words while "phase" must 00243 * point to an XML phase object, it must have 00244 * sibling nodes "speciesData" that describe 00245 * the species in the phase. 00246 * @param th Pointer to the ThermoPhase object which will 00247 * handle the thermodynamics for this phase. 00248 * We initialize part of the Thermophase object 00249 * here, especially for those objects which are 00250 * part of the Cantera Kernel. 00251 * 00252 * @param spfactory species Thermo factory pointer, if 00253 * available. If not available, one will be 00254 * created. 00255 * 00256 * @ingroup thermoprops 00257 */ 00258 bool importPhase(XML_Node& phase, ThermoPhase* th, 00259 SpeciesThermoFactory* spfactory = 0); 00260 00261 //! Install a species into a ThermoPhase object, which defines 00262 //! the phase thermodynamics and speciation. 00263 /*! 00264 * This routine first gathers the information from the Species XML 00265 * tree and calls addUniqueSpecies() to add it to the 00266 * ThermoPhase object, p. 00267 * This information consists of: 00268 * ecomp[] = element composition of species. 00269 * chgr = electric charge of species 00270 * name = string name of species 00271 * sz = size of the species 00272 * (option double used a lot in thermo) 00273 * 00274 * Then, the routine processes the "thermo" XML element and 00275 * calls underlying utility routines to read the XML elements 00276 * containing the thermodynamic information for the reference 00277 * state of the species. Failures or lack of information trigger 00278 * an "UnknownSpeciesThermoModel" exception being thrown. 00279 * 00280 * @param k Species Index in the phase 00281 * @param s XML_Node containing the species data for this species. 00282 * @param p Reference to the ThermoPhase object. 00283 * @param spthermo_ptr Reference to the SpeciesThermo object, where 00284 * the standard state thermo properties for this 00285 * species will be installed. 00286 * @param rule Parameter that handles what to do with species 00287 * who have elements that aren't declared. 00288 * Check that all elements in the species 00289 * exist in 'p'. If rule != 0, quietly skip 00290 * this species if some elements are undeclared; 00291 * otherwise, throw an exception 00292 * @param phaseNode_ptr Pointer to the XML_Node for this phase 00293 * (defaults to 0) 00294 * @param vpss_ptr pointer to the Manager that calculates standard 00295 * state thermo properties 00296 * @param factory Pointer to the SpeciesThermoFactory . 00297 * (defaults to 0) 00298 * 00299 * @return 00300 * Returns true if everything is ok, false otherwise. 00301 */ 00302 bool installSpecies(int k, const XML_Node& s, thermo_t& p, 00303 SpeciesThermo* spthermo_ptr, int rule, 00304 XML_Node *phaseNode_ptr = 0, 00305 VPSSMgr *vpss_ptr = 0, 00306 SpeciesThermoFactory* factory = 0); 00307 00308 //!Search an XML tree for species data. 00309 /*! 00310 * This utility routine will search the XML tree for the species 00311 * named by the string, kname. It will return the XML_Node 00312 * pointer to the species data for that species. 00313 * Failures of any kind return the null pointer. 00314 * 00315 * @param kname String containing the name of the species. 00316 * @param phaseSpeciesData Pointer to the XML speciesData element 00317 * containing the species data for that phase. 00318 * 00319 * 00320 */ 00321 const XML_Node *speciesXML_Node(std::string kname, 00322 const XML_Node *phaseSpeciesData); 00323 00324 //@} 00325 00326 } 00327 00328 #endif 00329 00330