Cantera  2.0
VPSSMgrFactory.cpp
Go to the documentation of this file.
1 /**
2  * @file VPSSMgrFactory.cpp
3  * Definitions for factory to build instances of classes that manage the
4  * calculation of standard state properties for all the species in a phase
5  * (see \ref spthermo and class
6  * \link Cantera::VPSSMgrFactory VPSSMgrFactory\endlink);
7  */
8 /*
9  * Copyright (2005) Sandia Corporation. Under the terms of
10  * Contract DE-AC04-94AL85000 with Sandia Corporation, the
11  * U.S. Government retains certain rights in this software.
12  */
13 
15 
16 #include "cantera/thermo/VPSSMgr.h"
17 #include "VPSSMgrFactory.h"
18 
20 
26 
28 
34 
35 #include "cantera/thermo/mix_defs.h"
36 
37 #include "cantera/base/xml.h"
38 #include "cantera/base/ctml.h"
39 
40 using namespace ctml;
41 using namespace std;
42 
43 namespace Cantera
44 {
45 
46 VPSSMgrFactory* VPSSMgrFactory::s_factory = 0;
47 
48 // Defn of the static mutex variable that locks the %VPSSMgr factory singleton
49 mutex_t VPSSMgrFactory::vpss_species_thermo_mutex;
50 
51 //! Examine the types of species thermo parameterizations, and return a flag indicating the type of parameterization
52 //! needed by the species.
53 /*!
54  *
55  * @param spDataNodeList Species Data XML node. This node contains a list
56  * of species XML nodes underneath it.
57  * @param has_nasa_idealGas Boolean indicating that one species has a nasa ideal gas standard state
58  * @param has_nasa_constVol Boolean indicating that one species has a nasa ideal solution standard state
59  * @param has_shomate_idealGas Boolean indicating that one species has a shomate ideal gas standard state
60  * @param has_shomate_constVol Boolean indicating that one species has a shomate ideal solution standard state
61  * @param has_simple_idealGas Boolean indicating that one species has a simple ideal gas standard state
62  * @param has_simple_constVol Boolean indicating that one species has a simple ideal solution standard state
63  * @param has_water Boolean indicating that one species has a water standard state
64  * @param has_tpx Boolean indicating that one species has a tpx standard state
65  * @param has_hptx Boolean indicating that one species has a htpx standard state
66  * @param has_other Boolean indicating that one species has different standard state than the ones listed above
67  *
68  * @todo Make sure that spDadta_node is species Data XML node by checking
69  * its name is speciesData
70  */
71 static void getVPSSMgrTypes(std::vector<XML_Node*> & spDataNodeList,
72  int& has_nasa_idealGas,
73  int& has_nasa_constVol,
74  int& has_shomate_idealGas,
75  int& has_shomate_constVol,
76  int& has_simple_idealGas,
77  int& has_simple_constVol,
78  int& has_water,
79  int& has_tpx,
80  int& has_hptx,
81  int& has_other)
82 {
83 
84  XML_Node* ss_ptr = 0;
85  string ssModel = "idealGas";
86  size_t ns = spDataNodeList.size();
87  for (size_t n = 0; n < ns; n++) {
88  bool ifound = false;
89  XML_Node* spNode = spDataNodeList[n];
90  if (spNode->hasChild("standardState")) {
91  const XML_Node& ssN = spNode->child("standardState");
92  string mm = ssN["model"];
93  if (mm == "waterIAPWS" || mm == "waterPDSS") {
94  has_water++;
95  ifound = true;
96  }
97  if (mm == "HKFT") {
98  has_hptx++;
99  ifound = true;
100  }
101  }
102  if (!ifound) {
103  if (spNode->hasChild("thermo")) {
104  const XML_Node& th = spNode->child("thermo");
105  if (spNode->hasChild("standardState")) {
106  ss_ptr = &(spNode->child("standardState"));
107  ssModel = ss_ptr->attrib("model");
108  }
109  if (th.hasChild("NASA")) {
110  if (ssModel == "idealGas") {
111  has_nasa_idealGas++;
112  } else if (ssModel == "constant_incompressible" ||
113  ssModel == "constantVolume") {
114  has_nasa_constVol++;
115  } else if (ssModel == "temperature_polynomial" ||
116  ssModel == "density_temperature_polynomial" ||
117  ssModel == "constant") {
118  has_other++;
119  } else {
120  throw UnknownVPSSMgrModel("getVPSSMgrTypes:",
121  spNode->attrib("name"));
122  }
123  ifound = true;
124  }
125  if (th.hasChild("Shomate")) {
126  if (ssModel == "idealGas") {
127  has_shomate_idealGas++;
128  } else if (ssModel == "constant_incompressible" ||
129  ssModel == "constantVolume") {
130  has_shomate_constVol++;
131  } else if (ssModel == "temperature_polynomial" ||
132  ssModel == "density_temperature_polynomial" ||
133  ssModel == "constant") {
134  has_other++;
135  } else {
136  throw UnknownVPSSMgrModel("getVPSSMgrTypes:",
137  spNode->attrib("name"));
138  }
139  ifound = true;
140  }
141  if (th.hasChild("const_cp")) {
142  if (ssModel == "idealGas") {
143  has_simple_idealGas++;
144  } else if (ssModel == "constant_incompressible" ||
145  ssModel == "constantVolume") {
146  has_simple_constVol++;
147  } else if (ssModel == "temperature_polynomial" ||
148  ssModel == "density_temperature_polynomial" ||
149  ssModel == "constant") {
150  has_other++;
151  } else {
152  throw UnknownVPSSMgrModel("getVPSSMgrTypes:",
153  spNode->attrib("name"));
154  }
155  ifound = true;
156  }
157  if (th.hasChild("poly")) {
158  if (th.child("poly")["order"] == "1") {
159  has_simple_constVol = 1;
160  ifound = true;
161  } else throw CanteraError("newSpeciesThermo",
162  "poly with order > 1 not yet supported");
163  }
164  if (th.hasChild("Mu0")) {
165  has_other++;
166  ifound = true;
167  }
168  if (th.hasChild("NASA9")) {
169  has_other++;
170  ifound = true;
171  }
172  if (th.hasChild("NASA9MULTITEMP")) {
173  has_other++;
174  ifound = true;
175  }
176  if (th.hasChild("adsorbate")) {
177  has_other++;
178  ifound = true;
179  }
180  if (th.hasChild("HKFT")) {
181  has_hptx++;
182  ifound = true;
183  }
184  } else {
185  throw UnknownVPSSMgrModel("getVPSSMgrTypes:",
186  spNode->attrib("name"));
187  }
188  }
189  }
190 }
191 
192 // Delete static instance of this class
193 /*
194  * If it is necessary to explicitly delete the factory before
195  * the process terminates (for example, when checking for
196  * memory leaks) then this method can be called to delete it.
197  */
198 void VPSSMgrFactory::deleteFactory()
199 {
200  ScopedLock lock(vpss_species_thermo_mutex);
201  if (s_factory) {
202  delete s_factory;
203  s_factory = 0;
204  }
205 }
206 
207 VPSSMgrFactory::~VPSSMgrFactory()
208 {
209 }
210 
212 VPSSMgrFactory::VPSSMgr_StringConversion(std::string ssModel) const
213 {
214  std::string lssModel = lowercase(ssModel);
215  VPSSMgr_enumType type;
216  if (lssModel == "idealgas") {
217  type = cVPSSMGR_IDEALGAS;
218  } else if (lssModel == "constvol") {
219  type = cVPSSMGR_CONSTVOL;
220  } else if (lssModel == "purefuild") {
221  type = cVPSSMGR_PUREFLUID;
222  } else if (lssModel == "water_constvol") {
223  type = cVPSSMGR_WATER_CONSTVOL;
224  } else if (lssModel == "water_hkft") {
225  type = cVPSSMGR_WATER_HKFT;
226  } else if (lssModel == "general") {
227  type = cVPSSMGR_GENERAL;
228  } else {
229  type = cVPSSMGR_UNDEF;
230  }
231  return type;
232 }
233 
234 // Chose the variable pressure standard state manager
235 // and the reference standard state manager
236 VPSSMgr*
238  XML_Node* phaseNode_ptr,
239  std::vector<XML_Node*> & spDataNodeList)
240 {
241 
242  std::string ssManager="";
243  std::string vpssManager="";
244  VPSSMgr* vpss = 0;
245 
246  // First look for any explicit instructions within the XML Database
247  // for the standard state manager and the variable pressure
248  // standard state manager
249  if (phaseNode_ptr) {
250  if (phaseNode_ptr->hasChild("thermo")) {
251  const XML_Node& thermoNode = phaseNode_ptr->child("thermo");
252  if (thermoNode.hasChild("standardStateManager")) {
253  const XML_Node& ssNode = thermoNode.child("standardStateManager");
254  ssManager = ssNode["model"];
255  }
256  if (thermoNode.hasChild("variablePressureStandardStateManager")) {
257  const XML_Node& vpssNode = thermoNode.child("variablePressureStandardStateManager");
258  vpssManager = vpssNode["model"];
259  }
260  }
261  }
262 
263  // first get the reference state handler. If we have explicit instructions,
264  // use them to spawn the object.
265  SpeciesThermo* spth = 0;
266  if (ssManager != "") {
267  spth = newSpeciesThermoMgr(ssManager);
268  } else {
269  spth = newSpeciesThermoMgr(spDataNodeList);
270  }
271  vp_ptr->setSpeciesThermo(spth);
272 
273  // Next, if we have specific directions, use them to get the VPSSSMgr object
274  // and return immediately
275  if (vpssManager != "") {
276  VPSSMgr_enumType type = VPSSMgr_StringConversion(vpssManager);
277  vpss = newVPSSMgr(type, vp_ptr);
278  return vpss;
279  }
280 
281  // Handle special cases based on the VPStandardState types
282  if (vp_ptr->eosType() == cVPSS_IdealGas) {
283  vpss = new VPSSMgr_IdealGas(vp_ptr, spth);
284  return vpss;
285  } else if (vp_ptr->eosType() == cVPSS_ConstVol) {
286  vpss = new VPSSMgr_ConstVol(vp_ptr, spth);
287  return vpss;
288  }
289 
290 
291  int inasaIG = 0, inasaCV = 0, ishomateIG = 0, ishomateCV = 0,
292  isimpleIG = 0, isimpleCV = 0,
293  iwater = 0, itpx = 0, iother = 0;
294  int ihptx = 0;
295 
296  try {
297  getVPSSMgrTypes(spDataNodeList, inasaIG, inasaCV, ishomateIG, ishomateCV,
298  isimpleIG, isimpleCV, iwater, itpx, ihptx, iother);
299  } catch (UnknownSpeciesThermoModel) {
300  iother = 1;
301  popError();
302  }
303 
304  if (iwater == 1) {
305  if (ihptx == 0) {
306  if (inasaIG || ishomateIG || isimpleIG) {
307  throw CanteraError("newVPSSMgr", "Ideal gas with liquid water");
308  } else {
309  vpss = new VPSSMgr_Water_ConstVol(vp_ptr, spth);
310  }
311  } else {
312  if (inasaIG || ishomateIG || isimpleIG) {
313  throw CanteraError("newVPSSMgr", "Ideal gas with liquid water");
314  } else if (inasaCV || ishomateCV || isimpleCV) {
315  vpss = new VPSSMgr_General(vp_ptr, spth);
316  } else {
317  vpss = new VPSSMgr_Water_HKFT(vp_ptr, spth);
318  }
319  }
320  }
321  if (vpss == 0) {
322  if (inasaCV || ishomateCV || isimpleCV) {
323  if (!inasaIG && !ishomateIG && !isimpleIG && !itpx && !ihptx && !iother) {
324  vpss = new VPSSMgr_ConstVol(vp_ptr, spth);
325  }
326  }
327  }
328  if (vpss == 0) {
329  vpss = new VPSSMgr_General(vp_ptr, spth);
330  }
331  return vpss;
332 }
333 
334 
335 
336 // I don't think this is currently used. However, this is a virtual
337 // function where additional capabilities may be added.
338 VPSSMgr*
340 {
341  SpeciesThermo& spthermoRef = vp_ptr->speciesThermo();
342  switch (type) {
343  case cVPSSMGR_IDEALGAS:
344  return new VPSSMgr_IdealGas(vp_ptr, &spthermoRef);
345  case cVPSSMGR_CONSTVOL:
346  return new VPSSMgr_ConstVol(vp_ptr, &spthermoRef);
347  case cVPSSMGR_PUREFLUID:
348  throw CanteraError("VPSSMgrFactory::newVPSSMgr",
349  "unimplemented");
350  case cVPSSMGR_WATER_CONSTVOL:
351  return new VPSSMgr_Water_ConstVol(vp_ptr, &spthermoRef);
352  case cVPSSMGR_WATER_HKFT:
353  return new VPSSMgr_Water_HKFT(vp_ptr, &spthermoRef);
354  case cVPSSMGR_GENERAL:
355  return new VPSSMgr_General(vp_ptr, &spthermoRef);
356  case cVPSSMGR_UNDEF:
357  default:
358  throw UnknownVPSSMgrModel("VPSSMgrFactory::newVPSSMgr", int2str(type));
359  return 0;
360  }
361 }
362 
363 // I don't think this is currently used
366 {
367  if (f == 0) {
368  f = VPSSMgrFactory::factory();
369  }
370  VPSSMgr* vpsssptherm = f->newVPSSMgr(type, vp_ptr);
371  return vpsssptherm;
372 }
373 
374 
376  XML_Node* phaseNode_ptr,
377  std::vector<XML_Node*> & spDataNodeList,
378  VPSSMgrFactory* f)
379 {
380  if (f == 0) {
381  f = VPSSMgrFactory::factory();
382  }
383  VPSSMgr* vpsssptherm = f->newVPSSMgr(tp_ptr, phaseNode_ptr, spDataNodeList);
384  return vpsssptherm;
385 }
386 
387 
388 }