Cantera  2.0
PDSS_SSVol.cpp
Go to the documentation of this file.
1 /**
2  * @file PDSS_SSVol.cpp
3  * Implementation of a pressure dependent standard state
4  * virtual function.
5  */
6 /*
7  * Copyright (2006) Sandia Corporation. Under the terms of
8  * Contract DE-AC04-94AL85000 with Sandia Corporation, the
9  * U.S. Government retains certain rights in this software.
10  */
11 #include "cantera/base/ct_defs.h"
12 #include "cantera/base/xml.h"
13 #include "cantera/base/ctml.h"
16 
18 
19 #include <fstream>
20 
21 using namespace std;
22 
23 namespace Cantera
24 {
25 /**
26  * Basic list of constructors and duplicators
27  */
28 
29 PDSS_SSVol::PDSS_SSVol(VPStandardStateTP* tp, size_t spindex) :
30  PDSS(tp, spindex),
31  volumeModel_(cSSVOLUME_CONSTANT),
32  m_constMolarVolume(-1.0)
33 {
34  m_pdssType = cPDSS_SSVOL;
35  TCoeff_[0] = 0.0;
36  TCoeff_[1] = 0.0;
37  TCoeff_[2] = 0.0;
38 }
39 
40 
42  size_t spindex, std::string inputFile, std::string id) :
43  PDSS(tp, spindex),
44  volumeModel_(cSSVOLUME_CONSTANT),
45  m_constMolarVolume(-1.0)
46 {
47 
48  m_pdssType = cPDSS_SSVOL;
49  constructPDSSFile(tp, spindex, inputFile, id);
50 }
51 
53  const XML_Node& speciesNode,
54  const XML_Node& phaseRoot,
55  bool spInstalled) :
56  PDSS(tp, spindex),
57  volumeModel_(cSSVOLUME_CONSTANT),
58  m_constMolarVolume(-1.0)
59 {
60  m_pdssType = cPDSS_SSVOL;
61  constructPDSSXML(tp, spindex, speciesNode, phaseRoot, spInstalled) ;
62 }
63 
64 
66  PDSS(b),
67  volumeModel_(cSSVOLUME_CONSTANT),
68  m_constMolarVolume(-1.0)
69 {
70  /*
71  * Use the assignment operator to do the brunt
72  * of the work for the copy constructor.
73  */
74  *this = b;
75 }
76 
77 /*
78  * Assignment operator
79  */
81 {
82  if (&b == this) {
83  return *this;
84  }
85  PDSS::operator=(b);
88  TCoeff_ = b.TCoeff_;
89  return *this;
90 }
91 
93 {
94 }
95 
96 //! Duplicator
98 {
99  PDSS_SSVol* idg = new PDSS_SSVol(*this);
100  return (PDSS*) idg;
101 }
102 
103 /*
104  * constructPDSSXML:
105  *
106  * Initialization of a PDSS_SSVol object using an
107  * xml file.
108  *
109  * This routine is a precursor to initThermo(XML_Node*)
110  * routine, which does most of the work.
111  *
112  * @param infile XML file containing the description of the
113  * phase
114  *
115  * @param id Optional parameter identifying the name of the
116  * phase. If none is given, the first XML
117  * phase element will be used.
118  */
120  const XML_Node& speciesNode,
121  const XML_Node& phaseNode, bool spInstalled)
122 {
125  m_p0 = sp.refPressure(m_spindex);
126 
127  if (!spInstalled) {
128  throw CanteraError("PDSS_SSVol::constructPDSSXML", "spInstalled false not handled");
129  }
130 
131  const XML_Node* ss = speciesNode.findByName("standardState");
132  if (!ss) {
133  throw CanteraError("PDSS_SSVol::constructPDSSXML",
134  "no standardState Node for species " + speciesNode.name());
135  }
136  std::string model = (*ss)["model"];
137  if (model == "constant_incompressible" || model == "constant") {
139  m_constMolarVolume = ctml::getFloat(*ss, "molarVolume", "toSI");
140  } else if (model == "temperature_polynomial") {
142  size_t num = ctml::getFloatArray(*ss, TCoeff_, true, "toSI", "volumeTemperaturePolynomial");
143  if (num != 4) {
144  throw CanteraError("PDSS_SSVol::constructPDSSXML",
145  " Didn't get 4 density polynomial numbers for species " + speciesNode.name());
146  }
147  } else if (model == "density_temperature_polynomial") {
149  size_t num = ctml::getFloatArray(*ss, TCoeff_, true, "toSI", "densityTemperaturePolynomial");
150  if (num != 4) {
151  throw CanteraError("PDSS_SSVol::constructPDSSXML",
152  " Didn't get 4 density polynomial numbers for species " + speciesNode.name());
153  }
154  } else {
155  throw CanteraError("PDSS_SSVol::constructPDSSXML",
156  "standardState model for species isn't constant_incompressible: " + speciesNode.name());
157  }
158  std::string id = "";
159 
160 }
161 
162 
163 /*
164  * constructPDSSFile():
165  *
166  * Initialization of a PDSS_SSVol object using an
167  * xml file.
168  *
169  * This routine is a precursor to initThermo(XML_Node*)
170  * routine, which does most of the work.
171  *
172  * @param infile XML file containing the description of the
173  * phase
174  *
175  * @param id Optional parameter identifying the name of the
176  * phase. If none is given, the first XML
177  * phase element will be used.
178  */
180  std::string inputFile, std::string id)
181 {
182 
183  if (inputFile.size() == 0) {
184  throw CanteraError("PDSS_SSVol::initThermo",
185  "input file is null");
186  }
187  std::string path = findInputFile(inputFile);
188  ifstream fin(path.c_str());
189  if (!fin) {
190  throw CanteraError("PDSS_SSVol::initThermo","could not open "
191  +path+" for reading.");
192  }
193  /*
194  * The phase object automatically constructs an XML object.
195  * Use this object to store information.
196  */
197 
198  XML_Node* fxml = new XML_Node();
199  fxml->build(fin);
200  XML_Node* fxml_phase = findXMLPhase(fxml, id);
201  if (!fxml_phase) {
202  throw CanteraError("PDSS_SSVol::initThermo",
203  "ERROR: Can not find phase named " +
204  id + " in file named " + inputFile);
205  }
206 
207  XML_Node& speciesList = fxml_phase->child("speciesArray");
208  XML_Node* speciesDB = get_XML_NameID("speciesData", speciesList["datasrc"],
209  &(fxml_phase->root()));
210  const vector<string>&sss = tp->speciesNames();
211  const XML_Node* s = speciesDB->findByAttr("name", sss[spindex]);
212 
213  constructPDSSXML(tp, spindex, *s, *fxml_phase, true);
214  delete fxml;
215 }
216 
217 void PDSS_SSVol::initThermoXML(const XML_Node& phaseNode, std::string& id)
218 {
219  PDSS::initThermoXML(phaseNode, id);
224 }
225 
227 {
230  m_p0 = sp.refPressure(m_spindex);
233 }
234 
235 doublereal
237 {
238  doublereal val = enthalpy_RT();
239  doublereal RT = GasConstant * m_temp;
240  return (val * RT);
241 }
242 
243 doublereal
245 {
246  doublereal val = m_hss_RT_ptr[m_spindex];
247  return (val);
248 }
249 
250 doublereal
252 {
253  doublereal pVRT = (m_pres * m_Vss_ptr[m_spindex]) / (GasConstant * m_temp);
254  doublereal val = m_h0_RT_ptr[m_spindex] - pVRT;
255  doublereal RT = GasConstant * m_temp;
256  return (val * RT);
257 }
258 
259 
260 doublereal
262 {
263  doublereal val = entropy_R();
264  return (val * GasConstant);
265 }
266 
267 doublereal
269 {
270  doublereal val = m_sss_R_ptr[m_spindex];
271  return (val);
272 }
273 
274 /**
275  * Calculate the Gibbs free energy in mks units of
276  * J kmol-1 K-1.
277  */
278 doublereal
280 {
281  doublereal val = gibbs_RT();
282  doublereal RT = GasConstant * m_temp;
283  return (val * RT);
284 }
285 
286 doublereal
288 {
289  doublereal val = m_gss_RT_ptr[m_spindex];
290  return (val);
291 }
292 
293 doublereal
295 {
296  doublereal val = m_cpss_R_ptr[m_spindex];
297  return (val * GasConstant);
298 }
299 
300 doublereal
302 {
303  doublereal val = m_cpss_R_ptr[m_spindex];
304  return (val);
305 }
306 
307 doublereal
309 {
310  doublereal val = (cp_mole() - m_V0_ptr[m_spindex]);
311  return (val);
312 }
313 
314 doublereal
316 {
317  doublereal val = m_Vss_ptr[m_spindex];
318  return (val);
319 }
320 
321 doublereal
323 {
324  doublereal val = m_Vss_ptr[m_spindex];
325  return (m_mw/val);
326 }
327 
328 doublereal
330 {
331  doublereal val = m_g0_RT_ptr[m_spindex];
332  return (val);
333 }
334 
335 doublereal PDSS_SSVol::enthalpy_RT_ref() const
336 {
337  doublereal val = m_h0_RT_ptr[m_spindex];
338  return (val);
339 }
340 
341 doublereal PDSS_SSVol::entropy_R_ref() const
342 {
343  doublereal val = m_s0_R_ptr[m_spindex];
344  return (val);
345 }
346 
347 doublereal PDSS_SSVol::cp_R_ref() const
348 {
349  doublereal val = m_cp0_R_ptr[m_spindex];
350  return (val);
351 }
352 
353 doublereal PDSS_SSVol::molarVolume_ref() const
354 {
355  doublereal val = m_V0_ptr[m_spindex];
356  return (val);
357 }
358 
360 {
363  } else if (volumeModel_ == cSSVOLUME_TPOLY) {
364  m_Vss_ptr[m_spindex] = TCoeff_[0] + m_temp * (TCoeff_[1] + m_temp * (TCoeff_[2] + m_temp * TCoeff_[3]));
365  dVdT_ = TCoeff_[1] + 2.0 * m_temp * TCoeff_[2] + 3.0 * m_temp * m_temp * TCoeff_[3];
366  d2VdT2_ = 2.0 * TCoeff_[2] + 6.0 * m_temp * TCoeff_[3];
367  } else if (volumeModel_ == cSSVOLUME_DENSITY_TPOLY) {
368  doublereal dens = TCoeff_[0] + m_temp * (TCoeff_[1] + m_temp * (TCoeff_[2] + m_temp * TCoeff_[3]));
369  m_Vss_ptr[m_spindex] = m_mw / dens;
370  doublereal dens2 = dens * dens;
371  doublereal ddensdT = TCoeff_[1] + 2.0 * m_temp * TCoeff_[2] + 3.0 * m_temp * m_temp * TCoeff_[3];
372  doublereal d2densdT2 = 2.0 * TCoeff_[2] + 6.0 * m_temp * TCoeff_[3];
373  dVdT_ = - m_mw / (dens2) * (ddensdT);
374  d2VdT2_ = 2.0 * m_mw / (dens2 * dens) * ddensdT * ddensdT - m_mw / dens2 * d2densdT2;
375  } else {
376  throw CanteraError("PDSS_SSVol::calcMolarVolume", "unimplemented");
377  }
378 }
379 
380 
381 /// critical temperature
382 doublereal PDSS_SSVol::critTemperature() const
383 {
384  throw CanteraError("PDSS_SSVol::critTemperature()", "unimplemented");
385  return (0.0);
386 }
387 
388 /// critical pressure
389 doublereal PDSS_SSVol::critPressure() const
390 {
391  throw CanteraError("PDSS_SSVol::critPressure()", "unimplemented");
392  return (0.0);
393 }
394 
395 /// critical density
396 doublereal PDSS_SSVol::critDensity() const
397 {
398  throw CanteraError("PDSS_SSVol::critDensity()", "unimplemented");
399  return (0.0);
400 }
401 
402 
403 
404 void PDSS_SSVol::setPressure(doublereal p)
405 {
406  m_pres = p;
407  doublereal deltaP = m_pres - m_p0;
408  if (fabs(deltaP) < 1.0E-10) {
413  } else {
414  doublereal del_pRT = deltaP / (GasConstant * m_temp);
415  doublereal sV_term = - deltaP / (GasConstant) * dVdT_;
416  m_hss_RT_ptr[m_spindex] = m_h0_RT_ptr[m_spindex] + sV_term + del_pRT * (m_Vss_ptr[m_spindex]);
420  }
421 }
422 
423 void PDSS_SSVol::setTemperature(doublereal temp)
424 {
425  m_temp = temp;
427  calcMolarVolume();
429  doublereal deltaP = m_pres - m_p0;
430  if (fabs(deltaP) < 1.0E-10) {
432  m_sss_R_ptr[m_spindex] = m_s0_R_ptr[m_spindex];
435  } else {
436  doublereal del_pRT = deltaP / (GasConstant * m_temp);
437  doublereal sV_term = - deltaP / (GasConstant) * dVdT_;
438  m_hss_RT_ptr[m_spindex] = m_h0_RT_ptr[m_spindex] + sV_term + del_pRT * (m_Vss_ptr[m_spindex]);
439  m_sss_R_ptr[m_spindex] = m_s0_R_ptr[m_spindex] + sV_term;
442  }
443 }
444 
445 
446 void PDSS_SSVol::setState_TP(doublereal temp, doublereal pres)
447 {
448  m_pres = pres;
449  setTemperature(temp);
450 }
451 
452 
453 void PDSS_SSVol::setState_TR(doublereal temp, doublereal rho)
454 {
455  doublereal rhoStored = m_mw / m_constMolarVolume;
456  if (fabs(rhoStored - rho) / (rhoStored + rho) > 1.0E-4) {
457  throw CanteraError("PDSS_SSVol::setState_TR",
458  "Inconsistent supplied rho");
459  }
460  setTemperature(temp);
461 }
462 
463 /// saturation pressure
464 doublereal PDSS_SSVol::satPressure(doublereal t)
465 {
466  return (1.0E-200);
467 }
468 
469 }