Cantera  2.0
VPStandardStateTP.cpp
Go to the documentation of this file.
1 /**
2  * @file VPStandardStateTP.cpp
3  * Definition file for a derived class of ThermoPhase that handles
4  * variable pressure standard state methods for calculating
5  * thermodynamic properties (see \ref thermoprops and
6  * class \link Cantera::VPStandardStateTP VPStandardStateTP\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 #include "cantera/thermo/VPSSMgr.h"
16 #include "cantera/thermo/PDSS.h"
18 
19 using namespace std;
20 
21 namespace Cantera
22 {
23 
24 /*
25  * Default constructor
26  */
27 VPStandardStateTP::VPStandardStateTP() :
28  ThermoPhase(),
29  m_Pcurrent(OneAtm),
30  m_Tlast_ss(-1.0),
31  m_Plast_ss(-1.0),
32  m_P0(OneAtm),
33  m_VPSS_ptr(0)
34 {
35 }
36 
37 /*
38  * Copy Constructor:
39  *
40  * Note this stuff will not work until the underlying phase
41  * has a working copy constructor.
42  *
43  * The copy constructor just calls the assignment operator
44  * to do the heavy lifting.
45  */
47  ThermoPhase(),
48  m_Pcurrent(OneAtm),
49  m_Tlast_ss(-1.0),
50  m_Plast_ss(-1.0),
51  m_P0(OneAtm),
52  m_VPSS_ptr(0)
53 {
55 }
56 
57 /*
58  * operator=()
59  *
60  * Note this stuff will not work until the underlying phase
61  * has a working assignment operator
62  */
65 {
66  if (&b != this) {
67  /*
68  * Mostly, this is a passthrough to the underlying
69  * assignment operator for the ThermoPhase parent object.
70  */
72  /*
73  * However, we have to handle data that we own.
74  */
78  m_P0 = b.m_P0;
79 
80  /*
81  * Duplicate the pdss objects
82  */
83  if (m_PDSS_storage.size() > 0) {
84  for (int k = 0; k < (int) m_PDSS_storage.size(); k++) {
85  delete(m_PDSS_storage[k]);
86  }
87  }
88  m_PDSS_storage.resize(m_kk);
89  for (size_t k = 0; k < m_kk; k++) {
90  PDSS* ptmp = b.m_PDSS_storage[k];
91  m_PDSS_storage[k] = ptmp->duplMyselfAsPDSS();
92  }
93 
94  /*
95  * Duplicate the VPSS Manager object that conducts the calculations
96  */
97  if (m_VPSS_ptr) {
98  delete m_VPSS_ptr;
99  m_VPSS_ptr = 0;
100  }
101  m_VPSS_ptr = (b.m_VPSS_ptr)->duplMyselfAsVPSSMgr();
102 
103  /*
104  * The VPSSMgr object contains shallow pointers. Whenever you have shallow
105  * pointers, they have to be fixed up to point to the correct objects referring
106  * back to this ThermoPhase's properties.
107  */
109  /*
110  * The PDSS objects contains shallow pointers. Whenever you have shallow
111  * pointers, they have to be fixed up to point to the correct objects referring
112  * back to this ThermoPhase's properties. This function also sets m_VPSS_ptr
113  * so it occurs after m_VPSS_ptr is set.
114  */
115  for (size_t k = 0; k < m_kk; k++) {
116  PDSS* ptmp = m_PDSS_storage[k];
117  ptmp->initAllPtrs(this, m_VPSS_ptr, m_spthermo);
118  }
119  /*
120  * Ok, the VPSSMgr object is ready for business.
121  * We need to resync the temperature and the pressure of the new standard states
122  * with what is stored in this object.
123  */
125  }
126  return *this;
127 }
128 //====================================================================================================================
129 /*
130  * ~VPStandardStateTP(): (virtual)
131  *
132  */
134 {
135  for (int k = 0; k < (int) m_PDSS_storage.size(); k++) {
136  delete(m_PDSS_storage[k]);
137  }
138  delete m_VPSS_ptr;
139 }
140 
141 /*
142  * Duplication function.
143  * This calls the copy constructor for this object.
144  */
146 {
147  VPStandardStateTP* vptp = new VPStandardStateTP(*this);
148  return (ThermoPhase*) vptp;
149 }
150 
151 // This method returns the convention used in specification
152 // of the standard state, of which there are currently two,
153 // temperature based, and variable pressure based.
154 /*
155  * Currently, there are two standard state conventions:
156  * - Temperature-based activities
157  * cSS_CONVENTION_TEMPERATURE 0
158  * - default
159  *
160  * - Variable Pressure and Temperature -based activities
161  * cSS_CONVENTION_VPSS 1
162  */
164 {
165  return cSS_CONVENTION_VPSS;
166 }
167 
168 
169 /*
170  * ------------Molar Thermodynamic Properties -------------------------
171  */
172 
173 
174 doublereal VPStandardStateTP::err(std::string msg) const
175 {
176  throw CanteraError("VPStandardStateTP","Base class method "
177  +msg+" called. Equation of state type: "+int2str(eosType()));
178  return 0;
179 }
180 
181 /*
182  * ---- Partial Molar Properties of the Solution -----------------
183  */
184 
185 /*
186  * Get the array of non-dimensional species chemical potentials
187  * These are partial molar Gibbs free energies.
188  * \f$ \mu_k / \hat R T \f$.
189  * Units: unitless
190  *
191  * We close the loop on this function, here, calling
192  * getChemPotentials() and then dividing by RT.
193  */
194 void VPStandardStateTP::getChemPotentials_RT(doublereal* muRT) const
195 {
196  getChemPotentials(muRT);
197  doublereal invRT = 1.0 / _RT();
198  for (size_t k = 0; k < m_kk; k++) {
199  muRT[k] *= invRT;
200  }
201 }
202 
203 /*
204  * ----- Thermodynamic Values for the Species Standard States States ----
205  */
207 {
208  getGibbs_RT(g);
209  doublereal RT = _RT();
210  for (size_t k = 0; k < m_kk; k++) {
211  g[k] *= RT;
212  }
213 }
214 
215 inline
216 void VPStandardStateTP::getEnthalpy_RT(doublereal* hrt) const
217 {
220 }
221 
222 //================================================================================================
223 #ifdef H298MODIFY_CAPABILITY
224 // Modify the value of the 298 K Heat of Formation of one species in the phase (J kmol-1)
225 /*
226  * The 298K heat of formation is defined as the enthalpy change to create the standard state
227  * of the species from its constituent elements in their standard states at 298 K and 1 bar.
228  *
229  * @param k Species k
230  * @param Hf298New Specify the new value of the Heat of Formation at 298K and 1 bar
231  */
232 void VPStandardStateTP::modifyOneHf298SS(const int k, const doublereal Hf298New)
233 {
234  m_spthermo->modifyOneHf298(k, Hf298New);
235  m_Tlast_ss += 0.0001234;
236 }
237 #endif
238 //================================================================================================
239 void VPStandardStateTP::getEntropy_R(doublereal* srt) const
240 {
242  m_VPSS_ptr->getEntropy_R(srt);
243 }
244 
245 inline
246 void VPStandardStateTP::getGibbs_RT(doublereal* grt) const
247 {
249  m_VPSS_ptr->getGibbs_RT(grt);
250 }
251 
252 inline
253 void VPStandardStateTP::getPureGibbs(doublereal* g) const
254 {
257 }
258 
259 void VPStandardStateTP::getIntEnergy_RT(doublereal* urt) const
260 {
263 }
264 
265 void VPStandardStateTP::getCp_R(doublereal* cpr) const
266 {
268  m_VPSS_ptr->getCp_R(cpr);
269 }
270 
271 void VPStandardStateTP::getStandardVolumes(doublereal* vol) const
272 {
275 }
276 
277 /*
278  * ----- Thermodynamic Values for the Species Reference States ----
279  */
280 
281 /*
282  * Returns the vector of nondimensional enthalpies of the
283  * reference state at the current temperature of the solution and
284  * the reference pressure for the species.
285  */
286 void VPStandardStateTP::getEnthalpy_RT_ref(doublereal* hrt) const
287 {
290 }
291 
292 /*
293  * Returns the vector of nondimensional
294  * enthalpies of the reference state at the current temperature
295  * of the solution and the reference pressure for the species.
296  */
297 void VPStandardStateTP::getGibbs_RT_ref(doublereal* grt) const
298 {
301 }
302 
303 /*
304  * Returns the vector of the
305  * gibbs function of the reference state at the current temperature
306  * of the solution and the reference pressure for the species.
307  * units = J/kmol
308  *
309  * This is filled in here so that derived classes don't have to
310  * take care of it.
311  */
312 void VPStandardStateTP::getGibbs_ref(doublereal* g) const
313 {
316 }
317 
318 const vector_fp& VPStandardStateTP::Gibbs_RT_ref() const
319 {
321  return m_VPSS_ptr->Gibbs_RT_ref();
322 }
323 
324 /*
325  * Returns the vector of nondimensional
326  * entropies of the reference state at the current temperature
327  * of the solution and the reference pressure for the species.
328  */
329 void VPStandardStateTP::getEntropy_R_ref(doublereal* er) const
330 {
333 }
334 
335 /*
336  * Returns the vector of nondimensional
337  * constant pressure heat capacities of the reference state
338  * at the current temperature of the solution
339  * and reference pressure for the species.
340  */
341 void VPStandardStateTP::getCp_R_ref(doublereal* cpr) const
342 {
344  m_VPSS_ptr->getCp_R_ref(cpr);
345 }
346 
347 /*
348  * Get the molar volumes of the species reference states at the current
349  * <I>T</I> and <I>P_ref</I> of the solution.
350  *
351  * units = m^3 / kmol
352  */
353 void VPStandardStateTP::getStandardVolumes_ref(doublereal* vol) const
354 {
357 }
358 
359 /*
360  * Perform initializations after all species have been
361  * added.
362  */
364 {
365  initLengths();
368  for (size_t k = 0; k < m_kk; k++) {
369  PDSS* kPDSS = m_PDSS_storage[k];
370  if (kPDSS) {
371  kPDSS->initThermo();
372  }
373  }
374 }
375 
377 {
378  m_VPSS_ptr = vp_ptr;
379 }
380 
381 /*
382  * Initialize the internal lengths.
383  * (this is not a virtual function)
384  */
386 {
387  m_kk = nSpecies();
388 
389 }
390 
391 
392 void VPStandardStateTP::setTemperature(const doublereal temp)
393 {
394  setState_TP(temp, m_Pcurrent);
396 }
397 
399 {
400  setState_TP(temperature(), p);
402 }
403 
405 {
406  err("VPStandardStateTP::calcDensity() called, but EOS for phase is not known");
407 }
408 
409 
410 void VPStandardStateTP::setState_TP(doublereal t, doublereal pres)
411 {
412  /*
413  * A pretty tricky algorithm is needed here, due to problems involving
414  * standard states of real fluids. For those cases you need
415  * to combine the T and P specification for the standard state, or else
416  * you may venture into the forbidden zone, especially when nearing the
417  * triple point.
418  * Therefore, we need to do the standard state thermo calc with the
419  * (t, pres) combo.
420  */
422  m_Pcurrent = pres;
424  /*
425  * Now, we still need to do the calculations for general ThermoPhase objects.
426  * So, we switch back to a virtual function call, setTemperature, and
427  * setPressure to recalculate stuff for child ThermoPhase objects of
428  * the VPStandardStateTP object. At this point,
429  * we haven't touched m_tlast or m_plast, so some calculations may still
430  * need to be done at the ThermoPhase object level.
431  */
432  //setTemperature(t);
433  //setPressure(pres);
434  calcDensity();
435 }
436 
437 
438 
439 void
440 VPStandardStateTP::createInstallPDSS(size_t k, const XML_Node& s,
441  const XML_Node* phaseNode_ptr)
442 {
443  if (m_PDSS_storage.size() < k+1) {
444  m_PDSS_storage.resize(k+1,0);
445  }
446  if (m_PDSS_storage[k] != 0) {
447  delete m_PDSS_storage[k] ;
448  }
449  m_PDSS_storage[k] = m_VPSS_ptr->createInstallPDSS(k, s, phaseNode_ptr);
450 }
451 
452 PDSS*
453 VPStandardStateTP::providePDSS(size_t k)
454 {
455  return m_PDSS_storage[k];
456 }
457 
458 const PDSS*
459 VPStandardStateTP::providePDSS(size_t k) const
460 {
461  return m_PDSS_storage[k];
462 }
463 
464 /*
465  * Import and initialize a ThermoPhase object
466  *
467  * param phaseNode This object must be the phase node of a
468  * complete XML tree
469  * description of the phase, including all of the
470  * species data. In other words while "phase" must
471  * point to an XML phase object, it must have
472  * sibling nodes "speciesData" that describe
473  * the species in the phase.
474  * param id ID of the phase. If nonnull, a check is done
475  * to see if phaseNode is pointing to the phase
476  * with the correct id.
477  *
478  * This routine initializes the lengths in the current object and
479  * then calls the parent routine.
480  */
481 void VPStandardStateTP::initThermoXML(XML_Node& phaseNode, std::string id)
482 {
484 
485  //m_VPSS_ptr->initThermo();
486  for (size_t k = 0; k < m_kk; k++) {
487  PDSS* kPDSS = m_PDSS_storage[k];
488  AssertTrace(kPDSS != 0);
489  if (kPDSS) {
490  kPDSS->initThermoXML(phaseNode, id);
491  }
492  }
493  m_VPSS_ptr->initThermoXML(phaseNode, id);
494  ThermoPhase::initThermoXML(phaseNode, id);
495 }
496 
497 
499 {
500  return m_VPSS_ptr;
501 }
502 
503 /*
504  * void _updateStandardStateThermo() (protected, virtual, const)
505  *
506  * If m_useTmpStandardStateStorage is true,
507  * This function must be called for every call to functions in this
508  * class that need standard state properties.
509  * Child classes may require that it be called even if m_useTmpStandardStateStorage
510  * is not true.
511  * It checks to see whether the temperature has changed and
512  * thus the ss thermodynamics functions for all of the species
513  * must be recalculated.
514  *
515  * This
516  */
518 {
519  double Tnow = temperature();
521  m_Tlast_ss = Tnow;
522  AssertThrowMsg(m_VPSS_ptr != 0, "VPStandardStateTP::_updateStandardStateThermo()",
523  "Probably indicates that ThermoPhase object wasn't initialized correctly");
525 }
526 
528 {
529  double Tnow = temperature();
530  if (Tnow != m_Tlast_ss || m_Pcurrent != m_Plast_ss) {
532  }
533 }
534 }
535 
536