Cantera  2.0
PDSS_IonsFromNeutral.cpp
Go to the documentation of this file.
1 /**
2  * @file PDSS_IonsFromNeutral.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 
17 #include "cantera/base/ct_defs.h"
18 #include "cantera/base/xml.h"
19 #include "cantera/base/ctml.h"
20 
21 #include <fstream>
22 
23 using namespace std;
24 
25 namespace Cantera
26 {
27 
28 //====================================================================================================================
29 PDSS_IonsFromNeutral::PDSS_IonsFromNeutral(VPStandardStateTP* tp, size_t spindex) :
30  PDSS(tp, spindex),
31  neutralMoleculePhase_(0),
32  numMult_(0),
33  add2RTln2_(true),
34  specialSpecies_(0)
35 {
36  m_pdssType = cPDSS_IONSFROMNEUTRAL;
37 }
38 //====================================================================================================================
40  std::string inputFile, std::string id) :
41  PDSS(tp, spindex),
42  neutralMoleculePhase_(0),
43  numMult_(0),
44  add2RTln2_(true),
45  specialSpecies_(0)
46 {
47  m_pdssType = cPDSS_IONSFROMNEUTRAL;
48  constructPDSSFile(tp, spindex, inputFile, id);
49 }
50 //====================================================================================================================
51 
53  const XML_Node& phaseRoot, bool spInstalled) :
54  PDSS(tp, spindex),
55  neutralMoleculePhase_(0),
56  numMult_(0),
57  add2RTln2_(true),
58  specialSpecies_(0)
59 {
60  if (!spInstalled) {
61  throw CanteraError("PDSS_IonsFromNeutral", "sp installing not done yet");
62  }
63  m_pdssType = cPDSS_IONSFROMNEUTRAL;
64  std::string id = "";
65  constructPDSSXML(tp, spindex, speciesNode, phaseRoot, id);
66 }
67 //====================================================================================================================
68 
70  PDSS(b)
71 {
72  /*
73  * Use the assignment operator to do the brunt
74  * of the work for the copy constructor.
75  */
76  *this = b;
77 }
78 //====================================================================================================================
79 /*
80  * Assignment operator
81  */
83 {
84  if (&b == this) {
85  return *this;
86  }
87 
88  PDSS::operator=(b);
89 
90  m_tmin = b.m_tmin;
91  m_tmax = b.m_tmax;
92 
93  /*
94  * The shallow pointer copy in the next step will be insufficient in most cases. However, its
95  * functionally the best we can do for this assignment operator. We fix up the pointer in the
96  * initAllPtrs() function.
97  */
99 
100  numMult_ = b.numMult_;
102  factorVec = b.factorVec;
104  tmpNM = b.tmpNM;
106 
107  return *this;
108 }
109 //====================================================================================================================
111 {
112 }
113 //====================================================================================================================
114 //! Duplicator
116 {
117  PDSS_IonsFromNeutral* idg = new PDSS_IonsFromNeutral(*this);
118  return (PDSS*) idg;
119 }
120 //====================================================================================================================
122  SpeciesThermo* spthermo)
123 {
124  PDSS::initAllPtrs(tp, vpssmgr_ptr, spthermo);
125 
126  IonsFromNeutralVPSSTP* ionPhase = dynamic_cast<IonsFromNeutralVPSSTP*>(tp);
127  if (!ionPhase) {
128  throw CanteraError("PDSS_IonsFromNeutral::initAllPts", "Dynamic cast failed");
129  }
131 }
132 //====================================================================================================================
133 // Initialization of a PDSS object using an xml tree
134 /*
135  * This routine is a driver for the initialization of the
136  * object.
137  *
138  * basic logic:
139  * initThermo() (cascade)
140  * getStuff from species Part of XML file
141  * initThermoXML(phaseNode) (cascade)
142  *
143  * @param vptp_ptr Pointer to the Variable pressure %ThermoPhase object
144  * This object must have already been malloced.
145  *
146  * @param spindex Species index within the phase
147  *
148  * @param phaseNode Reference to the phase Information for the phase
149  * that owns this species.
150  *
151  * @param id Optional parameter identifying the name of the
152  * phase. If none is given, the first XML
153  * phase element will be used.
154  */
156  const XML_Node& speciesNode,
157  const XML_Node& phaseNode, std::string id)
158 {
159  const XML_Node* tn = speciesNode.findByName("thermo");
160  if (!tn) {
161  throw CanteraError("PDSS_IonsFromNeutral::constructPDSSXML",
162  "no thermo Node for species " + speciesNode.name());
163  }
164  std::string model = lowercase((*tn)["model"]);
165  if (model != "ionfromneutral") {
166  throw CanteraError("PDSS_IonsFromNeutral::constructPDSSXML",
167  "thermo model for species isn't IonsFromNeutral: "
168  + speciesNode.name());
169  }
170  const XML_Node* nsm = tn->findByName("neutralSpeciesMultipliers");
171  if (!nsm) {
172  throw CanteraError("PDSS_IonsFromNeutral::constructPDSSXML",
173  "no Thermo::neutralSpeciesMultipliers Node for species " + speciesNode.name());
174  }
175 
176  IonsFromNeutralVPSSTP* ionPhase = dynamic_cast<IonsFromNeutralVPSSTP*>(tp);
177  if (!ionPhase) {
178  throw CanteraError("PDSS_IonsFromNeutral::constructPDSSXML", "Dynamic cast failed");
179  }
181 
182  std::vector<std::string> key;
183  std::vector<std::string> val;
184 
185  numMult_ = ctml::getPairs(*nsm, key, val);
187  factorVec.resize(numMult_);
189 
190  for (size_t i = 0; i < numMult_; i++) {
192  factorVec[i] = fpValueCheck(val[i]);
193  }
194  specialSpecies_ = 0;
195  const XML_Node* ss = tn->findByName("specialSpecies");
196  if (ss) {
197  specialSpecies_ = 1;
198  }
199  const XML_Node* sss = tn->findByName("secondSpecialSpecies");
200  if (sss) {
201  specialSpecies_ = 2;
202  }
203  add2RTln2_ = true;
204  if (specialSpecies_ == 1) {
205  add2RTln2_ = false;
206  }
207 
208 }
209 //====================================================================================================================
210 // Initialization of a PDSS object using an
211 // input XML file.
212 /*
213  *
214  * This routine is a precursor to constructPDSSXML(XML_Node*)
215  * routine, which does most of the work.
216  *
217  * @param vptp_ptr Pointer to the Variable pressure %ThermoPhase object
218  * This object must have already been malloced.
219  *
220  * @param spindex Species index within the phase
221  *
222  * @param inputFile XML file containing the description of the
223  * phase
224  *
225  * @param id Optional parameter identifying the name of the
226  * phase. If none is given, the first XML
227  * phase element will be used.
228  */
230  std::string inputFile, std::string id)
231 {
232 
233  if (inputFile.size() == 0) {
234  throw CanteraError("PDSS_IonsFromNeutral::constructPDSSFile",
235  "input file is null");
236  }
237  std::string path = findInputFile(inputFile);
238  ifstream fin(path.c_str());
239  if (!fin) {
240  throw CanteraError("PDSS_IonsFromNeutral::constructPDSSFile","could not open "
241  +path+" for reading.");
242  }
243  /*
244  * The phase object automatically constructs an XML object.
245  * Use this object to store information.
246  */
247 
248  XML_Node* fxml = new XML_Node();
249  fxml->build(fin);
250  XML_Node* fxml_phase = findXMLPhase(fxml, id);
251  if (!fxml_phase) {
252  throw CanteraError("PDSS_IonsFromNeutral::constructPDSSFile",
253  "ERROR: Can not find phase named " +
254  id + " in file named " + inputFile);
255  }
256 
257  XML_Node& speciesList = fxml_phase->child("speciesArray");
258  XML_Node* speciesDB = get_XML_NameID("speciesData", speciesList["datasrc"],
259  &(fxml_phase->root()));
260  const vector<string>&sss = tp->speciesNames();
261 
262  const XML_Node* s = speciesDB->findByAttr("name", sss[spindex]);
263 
264  constructPDSSXML(tp, spindex, *s, *fxml_phase, id);
265  delete fxml;
266 }
267 //=======================================================================================================
268 void PDSS_IonsFromNeutral::initThermoXML(const XML_Node& phaseNode, std::string& id)
269 {
270  PDSS::initThermoXML(phaseNode, id);
271 }
272 //=======================================================================================================
274 {
277  m_p0 = sp.refPressure(m_spindex);
280 }
281 //=======================================================================================================
282 /*
283  * Return the molar enthalpy in units of J kmol-1
284  */
285 doublereal
287 {
288  doublereal val = enthalpy_RT();
289  doublereal RT = GasConstant * m_temp;
290  return (val * RT);
291 }
292 //=======================================================================================================
293 doublereal
295 {
297  doublereal val = 0.0;
298  for (size_t i = 0; i < numMult_; i++) {
299  size_t jNeut = idNeutralMoleculeVec[i];
300  val += factorVec[i] * tmpNM[jNeut];
301  }
302  return val;
303 }
304 //=======================================================================================================
305 /*
306  * Calculate the internal energy in mks units of
307  * J kmol-1
308  */
309 doublereal
311 {
312  doublereal val = m_h0_RT_ptr[m_spindex] - 1.0;
313  doublereal RT = GasConstant * m_temp;
314  return (val * RT);
315 }
316 //=======================================================================================================
317 /*
318  * Calculate the entropy in mks units of
319  * J kmol-1 K-1
320  */
321 doublereal
323 {
324  doublereal val = entropy_R();
325  return (val * GasConstant);
326 }
327 //=======================================================================================================
328 doublereal
330 {
332  doublereal val = 0.0;
333  for (size_t i = 0; i < numMult_; i++) {
334  size_t jNeut = idNeutralMoleculeVec[i];
335  val += factorVec[i] * tmpNM[jNeut];
336  }
337  if (add2RTln2_) {
338  val -= 2.0 * log(2.0);
339  }
340  return val;
341 }
342 //=======================================================================================================
343 /*
344  * Calculate the Gibbs free energy in mks units of
345  * J kmol-1 K-1.
346  */
347 doublereal
349 {
350  doublereal val = gibbs_RT();
351  doublereal RT = GasConstant * m_temp;
352  return (val * RT);
353 }
354 //=======================================================================================================
355 doublereal
357 {
359  doublereal val = 0.0;
360  for (size_t i = 0; i < numMult_; i++) {
361  size_t jNeut = idNeutralMoleculeVec[i];
362  val += factorVec[i] * tmpNM[jNeut];
363  }
364  if (add2RTln2_) {
365  val += 2.0 * log(2.0);
366  }
367  return val;
368 }
369 //=======================================================================================================
370 /*
371  * Calculate the constant pressure heat capacity
372  * in mks units of J kmol-1 K-1
373  */
374 doublereal
376 {
377  doublereal val = cp_R();
378  return (val * GasConstant);
379 }
380 //=======================================================================================================
381 doublereal
383 {
385  doublereal val = 0.0;
386  for (size_t i = 0; i < numMult_; i++) {
387  size_t jNeut = idNeutralMoleculeVec[i];
388  val += factorVec[i] * tmpNM[jNeut];
389  }
390  return val;
391 }
392 //=======================================================================================================
393 doublereal
395 {
397  doublereal val = 0.0;
398  for (size_t i = 0; i < numMult_; i++) {
399  size_t jNeut = idNeutralMoleculeVec[i];
400  val += factorVec[i] * tmpNM[jNeut];
401  }
402  return val;
403 }
404 //=======================================================================================================
405 doublereal
407 {
408  return (m_pres * m_mw / (GasConstant * m_temp));
409 }
410 
411 /*
412  * Calculate the constant volume heat capacity
413  * in mks units of J kmol-1 K-1
414  */
415 doublereal
417 {
418  throw CanteraError("PDSS_IonsFromNeutral::cv_mole()", "unimplemented");
419  return 0.0;
420 }
421 //====================================================================================================================
422 
423 doublereal
425 {
427  doublereal val = 0.0;
428  for (size_t i = 0; i < numMult_; i++) {
429  size_t jNeut = idNeutralMoleculeVec[i];
430  val += factorVec[i] * tmpNM[jNeut];
431  }
432  if (add2RTln2_) {
433  val += 2.0 * log(2.0);
434  }
435  return val;
436 }
437 //====================================================================================================================
439 {
441  doublereal val = 0.0;
442  for (size_t i = 0; i < numMult_; i++) {
443  size_t jNeut = idNeutralMoleculeVec[i];
444  val += factorVec[i] * tmpNM[jNeut];
445  }
446  return val;
447 }
448 //====================================================================================================================
450 {
452  doublereal val = 0.0;
453  for (size_t i = 0; i < numMult_; i++) {
454  size_t jNeut = idNeutralMoleculeVec[i];
455  val += factorVec[i] * tmpNM[jNeut];
456  }
457  if (add2RTln2_) {
458  val -= 2.0 * log(2.0);
459  }
460  return val;
461 }
462 //====================================================================================================================
464 {
466  doublereal val = 0.0;
467  for (size_t i = 0; i < numMult_; i++) {
468  size_t jNeut = idNeutralMoleculeVec[i];
469  val += factorVec[i] * tmpNM[jNeut];
470  }
471  return val;
472 }
473 //====================================================================================================================
475 {
477  doublereal val = 0.0;
478  for (size_t i = 0; i < numMult_; i++) {
479  size_t jNeut = idNeutralMoleculeVec[i];
480  val += factorVec[i] * tmpNM[jNeut];
481  }
482  return val;
483 }
484 //====================================================================================================================
485 /*
486  * Calculate the pressure (Pascals), given the temperature and density
487  * Temperature: kelvin
488  * rho: density in kg m-3
489  */
491 {
492  return m_pres;
493 }
494 //====================================================================================================================
496 {
497  m_pres = p;
499 }
500 
501 //====================================================================================================================
502 // critical temperature
504 {
505  throw CanteraError("PDSS_IonsFromNeutral::critTemperature()", "unimplemented");
506  return (0.0);
507 }
508 //====================================================================================================================
509 // critical pressure
511 {
512  throw CanteraError("PDSS_IonsFromNeutral::critPressure()", "unimplemented");
513  return (0.0);
514 }
515 //====================================================================================================================
516 // critical density
518 {
519  throw CanteraError("PDSS_IonsFromNeutral::critDensity()", "unimplemented");
520  return (0.0);
521 }
522 //====================================================================================================================
523 
524 /*
525  * Return the temperature
526  *
527  * Obtain the temperature from the owning VPStandardStateTP object
528  * if you can.
529  */
531 {
533  return m_temp;
534 }
535 //====================================================================================================================
537 {
538  m_temp = temp;
540 }
541 //====================================================================================================================
542 
543 void PDSS_IonsFromNeutral::setState_TP(doublereal temp, doublereal pres)
544 {
545  m_pres = pres;
546  m_temp = temp;
547  neutralMoleculePhase_->setState_TP(temp, pres);
548 }
549 //====================================================================================================================
550 void PDSS_IonsFromNeutral::setState_TR(doublereal temp, doublereal rho)
551 {
553 }
554 //====================================================================================================================
555 // saturation pressure
556 doublereal PDSS_IonsFromNeutral::satPressure(doublereal t)
557 {
558  throw CanteraError("PDSS_IonsFromNeutral::satPressure()", "unimplemented");
559  /*NOTREACHED*/
560  return (0.0);
561 }
562 //====================================================================================================================
563 
564 }
565 //====================================================================================================================