Cantera  2.0
SingleSpeciesTP.cpp
Go to the documentation of this file.
1 /**
2  * @file SingleSpeciesTP.cpp
3  * Definitions for the %SingleSpeciesTP class, which is a filter class for %ThermoPhase,
4  * that eases the construction of single species phases
5  * ( see \ref thermoprops and class \link Cantera::SingleSpeciesTP SingleSpeciesTP\endlink).
6  */
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  */
15 
16 using namespace std;
17 
18 namespace Cantera
19 {
20 
21 /*
22  * -------------- Constructors ------------------------------------
23  *
24  */
25 
26 // Base empty constructor.
27 /*
28  * Base constructor -> does nothing but called the inherited
29  * class constructor
30  */
31 SingleSpeciesTP::SingleSpeciesTP() :
32  ThermoPhase(),
33  m_tmin(0.0),
34  m_tmax(0.0),
35  m_press(OneAtm),
36  m_p0(OneAtm),
37  m_tlast(-1.0)
38 {
39 }
40 
41 
42 //! Copy constructor
43 /*!
44  * @param right Object to be copied
45  */
47  ThermoPhase(),
48  m_tmin(0.0),
49  m_tmax(0.0),
50  m_press(OneAtm),
51  m_p0(OneAtm),
52  m_tlast(-1.0)
53 {
54  *this = operator=(right);
55 }
56 
57 //! Assignment operator
58 /*!
59  * @param right Object to be copied
60  */
62 {
63  if (&right != this) {
65  m_tmin = right.m_tmin;
66  m_tmax = right.m_tmax;
67  m_press = right.m_press;
68  m_p0 = right.m_p0;
69  m_tlast = right.m_tlast;
70  m_h0_RT = right.m_h0_RT;
71  m_cp0_R = right.m_cp0_R;
72  m_s0_R = right.m_s0_R;
73  }
74  return *this;
75 }
76 
77 /*
78  * destructor -> does nothing but implicitly calls the inherited
79  * class destructors.
80  */
82 {
83 }
84 
85 //! Duplication function
86 /*!
87  * This virtual function is used to create a duplicate of the
88  * current phase. It's used to duplicate the phase when given
89  * a ThermoPhase pointer to the phase.
90  *
91  * @return It returns a ThermoPhase pointer.
92  */
94 {
95  SingleSpeciesTP* stp = new SingleSpeciesTP(*this);
96  return (ThermoPhase*) stp;
97 }
98 
99 /**
100  *
101  * ------------------- Utilities ----------------------------------
102  *
103  */
104 
105 /**
106  * eosType():
107  * Creates an error because this is not a fully formed
108  * class
109  */
111 {
112  err("eosType");
113  return -1;
114 }
115 
116 /**
117  * ------------ Molar Thermodynamic Properties --------------------
118  *
119  *
120  * For this single species template, the molar properties of
121  * the mixture are identified with the partial molar properties
122  * of species number 0. The partial molar property routines
123  * are called to evaluate these functions.
124  */
125 
126 /**
127  * enthalpy_mole():
128  *
129  * Molar enthalpy. Units: J/kmol.
130  */
132 {
133  double hbar;
135  return hbar;
136 }
137 
138 /**
139  * enthalpy_mole():
140  *
141  * Molar internal energy. Units: J/kmol.
142  */
144 {
145  double ubar;
147  return ubar;
148 }
149 
150 /**
151  * entropy_mole():
152  *
153  * Molar entropy of the mixture. Units: J/kmol/K.
154  */
156 {
157  double sbar;
159  return sbar;
160 }
161 
162 /**
163  * gibbs_mole():
164  *
165  * Molar Gibbs free energy of the mixture. Units: J/kmol/K.
166  */
167 doublereal SingleSpeciesTP::gibbs_mole() const
168 {
169  double gbar;
170  /*
171  * Get the chemical potential of the first species.
172  * This is the same as the partial molar Gibbs
173  * free energy.
174  */
175  getChemPotentials(&gbar);
176  return gbar;
177 }
178 
179 /**
180  * cp_mole():
181  *
182  * Molar heat capacity at constant pressure of the mixture.
183  * Units: J/kmol/K.
184  */
185 doublereal SingleSpeciesTP::cp_mole() const
186 {
187  double cpbar;
188  /*
189  * Really should have a partial molar heat capacity
190  * function in ThermoPhase. However, the standard
191  * state heat capacity will do fine here for now.
192  */
193  //getPartialMolarCp(&cpbar);
194  getCp_R(&cpbar);
195  cpbar *= GasConstant;
196  return cpbar;
197 }
198 
199 /*
200  * cv_mole():
201  *
202  * Molar heat capacity at constant volume of the mixture.
203  * Units: J/kmol/K.
204  *
205  * For single species, we go directory to the
206  * general Cp - Cv relation
207  *
208  * Cp = Cv + alpha**2 * V * T / beta
209  *
210  * where
211  * alpha = volume thermal expansion coefficient
212  * beta = isothermal compressibility
213  */
214 doublereal SingleSpeciesTP::cv_mole() const
215 {
216  doublereal cvbar = cp_mole();
217  doublereal alpha = thermalExpansionCoeff();
218  doublereal beta = isothermalCompressibility();
219  doublereal molecW = molecularWeight(0);
220  doublereal V = molecW/density();
221  doublereal T = temperature();
222  if (beta != 0.0) {
223  cvbar -= alpha * alpha * V * T / beta;
224  }
225  return cvbar;
226 }
227 
228 /*
229  * ----------- Chemical Potentials and Activities ----------------------
230  */
231 
232 /*
233  * ----------- Partial Molar Properties of the Solution -----------------
234  *
235  * These are calculated by reference to the standard state properties
236  * of the zeroeth species.
237  */
238 
239 
240 // Get the array of chemical potentials at unit activity
241 /*
242  * These are the standard state chemical potentials. \f$ \mu^0_k \f$.
243  *
244  * @param mu On return, Contains the chemical potential of the single species
245  * and the phase. Units are J / kmol . Length = 1
246  */
247 void SingleSpeciesTP::getChemPotentials(doublereal* mu) const
248 {
250 }
251 
252 
253 // Get the array of non-dimensional species chemical potentials
254 // These are partial molar Gibbs free energies.
255 /*
256  * These are the standard state dimensionless chemical potentials.
257  * \f$ \mu_k / \hat R T \f$.
258  *
259  * Units: unitless
260  *
261  * @param murt On return, Contains the chemical potential / RT of the single species
262  * and the phase. Units are unitless. Length = 1
263  */
264 void SingleSpeciesTP::getChemPotentials_RT(doublereal* murt) const
265 {
267  double rt = GasConstant * temperature();
268  murt[0] /= rt;
269 }
270 
271 // Get the species electrochemical potentials. Units: J/kmol.
272 /*
273  * This method adds a term \f$ Fz_k \phi_k \f$ to
274  * each chemical potential.
275  *
276  * This is resolved here. A single species phase
277  * is not allowed to have anything other than a zero charge.
278  *
279  * @param murt On return, Contains the chemical potential / RT of the single species
280  * and the phase. Units are unitless. Length = 1
281  */
283 {
284  getChemPotentials(mu);
285 }
286 
287 // Get the species partial molar enthalpies. Units: J/kmol.
288 /*
289  * These are the phase enthalpies. \f$ h_k \f$.
290  *
291  * @param hbar On return, Contains the enthalpy of the single species
292  * and the phase. Units are J / kmol . Length = 1
293  */
295 getPartialMolarEnthalpies(doublereal* hbar) const
296 {
297  double _rt = GasConstant * temperature();
298  getEnthalpy_RT(hbar);
299  hbar[0] *= _rt;
300 }
301 
302 // Get the species partial molar internal energies. Units: J/kmol.
303 /*
304  * These are the phase internal energies. \f$ u_k \f$.
305  *
306  * This member function is resolved here. A single species phase obtains its
307  * thermo from the standard state function.
308  *
309  * @param ubar On return, Contains the internal energy of the single species
310  * and the phase. Units are J / kmol . Length = 1
311  */
313 getPartialMolarIntEnergies(doublereal* ubar) const
314 {
315  double _rt = GasConstant * temperature();
316  getIntEnergy_RT(ubar);
317  ubar[0] *= _rt;
318 }
319 
320 // Get the species partial molar entropy. Units: J/kmol K.
321 /*
322  * This is the phase entropy. \f$ s(T,P) = s_o(T,P) \f$.
323  *
324  * This member function is resolved here. A single species phase obtains its
325  * thermo from the standard state function.
326  *
327  * @param sbar On return, Contains the entropy of the single species
328  * and the phase. Units are J / kmol / K . Length = 1
329  */
331 getPartialMolarEntropies(doublereal* sbar) const
332 {
333  getEntropy_R(sbar);
334  sbar[0] *= GasConstant;
335 }
336 
337 // Get the species partial molar Heat Capacities. Units: J/ kmol K.
338 /*
339  * This is the phase heat capacity. \f$ Cp(T,P) = Cp_o(T,P) \f$.
340  *
341  * This member function is resolved here. A single species phase obtains its
342  * thermo from the standard state function.
343  *
344  * @param cpbar On return, Contains the heat capacity of the single species
345  * and the phase. Units are J / kmol / K . Length = 1
346  */
347 void SingleSpeciesTP::getPartialMolarCp(doublereal* cpbar) const
348 {
349  getCp_R(cpbar);
350  cpbar[0] *= GasConstant;
351 }
352 
353 // Get the species partial molar volumes. Units: m^3/kmol.
354 /*
355  * This is the phase molar volume. \f$ V(T,P) = V_o(T,P) \f$.
356  *
357  * This member function is resolved here. A single species phase obtains its
358  * thermo from the standard state function.
359  *
360  * @param vbar On return, Contains the molar volume of the single species
361  * and the phase. Units are m^3 / kmol. Length = 1
362  */
363 void SingleSpeciesTP::getPartialMolarVolumes(doublereal* vbar) const
364 {
365  double mw = molecularWeight(0);
366  double dens = density();
367  vbar[0] = mw / dens;
368 }
369 
370 /*
371  * ----- Properties of the Standard State of the Species in the Solution
372  * -----
373  */
374 
375 /*
376  * Get the dimensional Gibbs functions for the standard
377  * state of the species at the current T and P.
378  */
379 void SingleSpeciesTP::getPureGibbs(doublereal* gpure) const
380 {
381  getGibbs_RT(gpure);
382  gpure[0] *= GasConstant * temperature();
383 }
384 
385 
386 // Get the molar volumes of each species in their standard
387 // states at the current <I>T</I> and <I>P</I> of the solution.
388 /*
389  * units = m^3 / kmol
390  *
391  * We resolve this function at this level, by assigning
392  * the molecular weight divided by the phase density
393  *
394  * @param vbar On output this contains the standard volume of the species
395  * and phase (m^3/kmol). Vector of length 1
396  */
397 void SingleSpeciesTP::getStandardVolumes(doublereal* vbar) const
398 {
399  double mw = molecularWeight(0);
400  double dens = density();
401  vbar[0] = mw / dens;
402 }
403 
404 /*
405  * ---- Thermodynamic Values for the Species Reference States -------
406  */
407 
408 
409 /**
410  * Returns the vector of nondimensional
411  * enthalpies of the reference state at the current temperature
412  * of the solution and the reference pressure for the species.
413  *
414  *
415  */
416 void SingleSpeciesTP::getEnthalpy_RT_ref(doublereal* hrt) const
417 {
418  _updateThermo();
419  hrt[0] = m_h0_RT[0];
420 }
421 
422 
423 /**
424  * Returns the vector of nondimensional
425  * enthalpies of the reference state at the current temperature
426  * of the solution and the reference pressure for the species.
427  */
428 void SingleSpeciesTP::getGibbs_RT_ref(doublereal* grt) const
429 {
430  _updateThermo();
431  grt[0] = m_h0_RT[0] - m_s0_R[0];
432 }
433 
434 /**
435  * Returns the vector of the
436  * gibbs function of the reference state at the current temperature
437  * of the solution and the reference pressure for the species.
438  * units = J/kmol
439  */
440 void SingleSpeciesTP::getGibbs_ref(doublereal* g) const
441 {
442  getGibbs_RT_ref(g);
443  g[0] *= GasConstant * temperature();
444 }
445 
446 /**
447  * Returns the vector of nondimensional
448  * entropies of the reference state at the current temperature
449  * of the solution and the reference pressure for the species.
450  */
451 void SingleSpeciesTP::getEntropy_R_ref(doublereal* er) const
452 {
453  _updateThermo();
454  er[0] = m_s0_R[0];
455 }
456 
457 /**
458  * Get the nondimensional Gibbs functions for the standard
459  * state of the species at the current T and reference pressure
460  * for the species.
461  */
462 void SingleSpeciesTP::getCp_R_ref(doublereal* cpr) const
463 {
464  _updateThermo();
465  cpr[0] = m_cp0_R[0];
466 }
467 
468 /*
469  * ------------------ Setting the State ------------------------
470  */
471 
472 
473 void SingleSpeciesTP::setState_TPX(doublereal t, doublereal p,
474  const doublereal* x)
475 {
476  setTemperature(t);
477  setPressure(p);
478 }
479 
480 void SingleSpeciesTP::setState_TPX(doublereal t, doublereal p,
481  compositionMap& x)
482 {
483  setTemperature(t);
484  setPressure(p);
485 }
486 
487 void SingleSpeciesTP::setState_TPX(doublereal t, doublereal p,
488  const std::string& x)
489 {
490  setTemperature(t);
491  setPressure(p);
492 }
493 
494 void SingleSpeciesTP::setState_TPY(doublereal t, doublereal p,
495  const doublereal* y)
496 {
497  setTemperature(t);
498  setPressure(p);
499 }
500 
501 void SingleSpeciesTP::setState_TPY(doublereal t, doublereal p,
502  compositionMap& y)
503 {
504  setTemperature(t);
505  setPressure(p);
506 }
507 
508 void SingleSpeciesTP::setState_TPY(doublereal t, doublereal p,
509  const std::string& y)
510 {
511  setTemperature(t);
512  setPressure(p);
513 }
514 
515 void SingleSpeciesTP::setState_PX(doublereal p, doublereal* x)
516 {
517  if (x[0] != 1.0) {
518  err("setStatePX -> x[0] not 1.0");
519  }
520  setPressure(p);
521 }
522 
523 void SingleSpeciesTP::setState_PY(doublereal p, doublereal* y)
524 {
525  if (y[0] != 1.0) {
526  err("setStatePY -> x[0] not 1.0");
527  }
528  setPressure(p);
529 }
530 
531 void SingleSpeciesTP::setState_HP(doublereal h, doublereal p,
532  doublereal tol)
533 {
534  doublereal dt;
535  setPressure(p);
536  for (int n = 0; n < 50; n++) {
537  dt = (h - enthalpy_mass())/cp_mass();
538  if (dt > 100.0) {
539  dt = 100.0;
540  } else if (dt < -100.0) {
541  dt = -100.0;
542  }
543  setState_TP(temperature() + dt, p);
544  if (fabs(dt) < tol) {
545  return;
546  }
547  }
548  throw CanteraError("setState_HP","no convergence. dt = " + fp2str(dt));
549 }
550 
551 void SingleSpeciesTP::setState_UV(doublereal u, doublereal v,
552  doublereal tol)
553 {
554  doublereal dt;
555  if (v == 0.0) {
556  setDensity(1.0E100);
557  } else {
558  setDensity(1.0/v);
559  }
560  for (int n = 0; n < 50; n++) {
561  dt = (u - intEnergy_mass())/cv_mass();
562  if (dt > 100.0) {
563  dt = 100.0;
564  } else if (dt < -100.0) {
565  dt = -100.0;
566  }
567  setTemperature(temperature() + dt);
568  if (fabs(dt) < tol) {
569  return;
570  }
571  }
572  throw CanteraError("setState_UV",
573  "no convergence. dt = " + fp2str(dt)+"\n"
574  +"u = "+fp2str(u)+" v = "+fp2str(v)+"\n");
575 }
576 
577 void SingleSpeciesTP::setState_SP(doublereal s, doublereal p,
578  doublereal tol)
579 {
580  doublereal dt;
581  setPressure(p);
582  for (int n = 0; n < 50; n++) {
583  dt = (s - entropy_mass())*temperature()/cp_mass();
584  if (dt > 100.0) {
585  dt = 100.0;
586  } else if (dt < -100.0) {
587  dt = -100.0;
588  }
589  setState_TP(temperature() + dt, p);
590  if (fabs(dt) < tol) {
591  return;
592  }
593  }
594  throw CanteraError("setState_SP","no convergence. dt = " + fp2str(dt));
595 }
596 
597 void SingleSpeciesTP::setState_SV(doublereal s, doublereal v,
598  doublereal tol)
599 {
600  doublereal dt;
601  if (v == 0.0) {
602  setDensity(1.0E100);
603  } else {
604  setDensity(1.0/v);
605  }
606  for (int n = 0; n < 50; n++) {
607  dt = (s - entropy_mass())*temperature()/cv_mass();
608  if (dt > 100.0) {
609  dt = 100.0;
610  } else if (dt < -100.0) {
611  dt = -100.0;
612  }
613  setTemperature(temperature() + dt);
614  if (fabs(dt) < tol) {
615  return;
616  }
617  }
618  throw CanteraError("setState_SV","no convergence. dt = " + fp2str(dt));
619 }
620 
621 /*
622  * This private function throws a cantera exception. It's used when
623  * this class doesn't have an answer for the question given to it,
624  * because the derived class isn't overriding a function.
625  */
626 doublereal SingleSpeciesTP::err(std::string msg) const
627 {
628  throw CanteraError("SingleSpeciesTP","Base class method "
629  +msg+" called. Equation of state type: "
630  +int2str(eosType()));
631  return 0;
632 }
633 
634 /*
635  * @internal Initialize. This method is provided to allow
636  * subclasses to perform any initialization required after all
637  * species have been added. For example, it might be used to
638  * resize internal work arrays that must have an entry for
639  * each species. The base class implementation does nothing,
640  * and subclasses that do not require initialization do not
641  * need to overload this method. When importing a CTML phase
642  * description, this method is called just prior to returning
643  * from function importPhase.
644  *
645  * Inheriting objects should call this function
646  *
647  * @see importCTML.cpp
648  */
650 {
651 
652  /*
653  * Make sure there is one and only one species in this phase.
654  */
655  m_kk = nSpecies();
656  if (m_kk != 1) {
657  throw CanteraError("initThermo",
658  "stoichiometric substances may only contain one species.");
659  }
660  doublereal tmin = m_spthermo->minTemp();
661  doublereal tmax = m_spthermo->maxTemp();
662  if (tmin > 0.0) {
663  m_tmin = tmin;
664  }
665  if (tmax > 0.0) {
666  m_tmax = tmax;
667  }
668 
669  /*
670  * Store the reference pressure in the variables for the class.
671  */
672  m_p0 = refPressure();
673 
674  /*
675  * Resize temporary arrays.
676  */
677  int leng = 1;
678  m_h0_RT.resize(leng);
679  m_cp0_R.resize(leng);
680  m_s0_R.resize(leng);
681 
682  /*
683  * Make sure the species mole fraction is equal to 1.0;
684  */
685  double x = 1.0;
686  setMoleFractions(&x);
687  /*
688  * Call the base class initThermo object.
689  */
691 }
692 
693 /*
694  * _updateThermo():
695  *
696  * This crucial internal routine calls the species thermo
697  * update program to calculate new species Cp0, H0, and
698  * S0 whenever the temperature has changed.
699  */
701 {
702  doublereal tnow = temperature();
703  if (m_tlast != tnow) {
705  DATA_PTR(m_s0_R));
706  m_tlast = tnow;
707  }
708 }
709 
710 }
711 
712 
713 
714