Cantera  2.0
PureFluidPhase.cpp
Go to the documentation of this file.
1 /**
2  * @file PureFluidPhase.cpp
3  * Definitions for a ThermoPhase object for a pure fluid phase consisting
4  * of gas, liquid, mixed-gas-liquid
5  * and supercritical fluid (see \ref thermoprops
6  * and class \link Cantera::PureFluidPhase PureFluidPhase\endlink).
7  */
8 #include "cantera/base/xml.h"
10 
11 #include "cantera/tpx/Sub.h"
12 #include "cantera/tpx/utils.h"
13 
14 #include <cstdlib>
15 #include <iomanip>
16 #include <fstream>
17 
18 using std::string;
19 using std::endl;
20 using std::setw;
21 
22 namespace Cantera
23 {
24 
25 // Base Constructor
27  ThermoPhase(),
28  m_sub(0),
29  m_subflag(0),
30  m_mw(-1.0),
31  m_verbose(false)
32 {
33 }
34 
35 // CopyConstructor
37  ThermoPhase(),
38  m_sub(0),
39  m_subflag(0),
40  m_mw(-1.0),
41  m_verbose(false)
42 {
43  *this = right;
44 }
45 
46 //! Assignment operator
47 /*!
48  * @param right Object to be copied
49  */
51 {
52  if (&right != this) {
54  if (m_sub) {
55  delete m_sub;
56  }
57  m_subflag = right.m_subflag;
58  m_sub = tpx::GetSub(m_subflag);
59  m_mw = right.m_mw;
60  m_verbose = right.m_verbose;
61  }
62  return *this;
63 }
64 
65 // Duplicator from the %ThermoPhase parent class
66 /*
67  * Given a pointer to a %ThermoPhase object, this function will
68  * duplicate the %ThermoPhase object and all underlying structures.
69  * This is basically a wrapper around the copy constructor.
70  *
71  * @return returns a pointer to a %ThermoPhase
72  */
74 {
75  PureFluidPhase* igp = new PureFluidPhase(*this);
76  return (ThermoPhase*) igp;
77 }
78 
79 
80 
81 
83 {
84  delete m_sub;
85 }
86 
89 {
90  if (m_sub) {
91  delete m_sub;
92  }
93  m_sub = tpx::GetSub(m_subflag);
94  if (m_sub == 0) {
95  throw CanteraError("PureFluidPhase::initThermo",
96  "could not create new substance object.");
97  }
98  m_mw = m_sub->MolWt();
100  double one = 1.0;
101  setMoleFractions(&one);
102  double cp0_R, h0_RT, s0_R, T0, p;
103  T0 = 298.15;
104  if (T0 < m_sub->Tcrit()) {
105  m_sub->Set(tpx::TX, T0, 1.0);
106  p = 0.01*m_sub->P();
107  } else {
108  p = 0.001*m_sub->Pcrit();
109  }
110  p = 0.001 * p;
111  m_sub->Set(tpx::TP, T0, p);
112 
113  m_spthermo->update_one(0, T0, &cp0_R, &h0_RT, &s0_R);
114  double s_R = s0_R - log(p/refPressure());
115  m_sub->setStdState(h0_RT*GasConstant*298.15/m_mw,
116  s_R*GasConstant/m_mw, T0, p);
117  if (m_verbose) {
118  writelog("PureFluidPhase::initThermo: initialized phase "
119  +id()+"\n");
120  }
121 }
122 
123 void PureFluidPhase::
125 {
126  eosdata._require("model","PureFluid");
127  m_subflag = atoi(eosdata["fluid_type"].c_str());
128  if (m_subflag < 0)
129  throw CanteraError("PureFluidPhase::setParametersFromXML",
130  "missing or negative substance flag");
131 }
132 
133 doublereal PureFluidPhase::
135 {
136  setTPXState();
137  doublereal h = m_sub->h() * m_mw;
138  check(h);
139  return h;
140 }
141 
142 doublereal PureFluidPhase::
144 {
145  setTPXState();
146  doublereal u = m_sub->u() * m_mw;
147  check(u);
148  return u;
149 }
150 
151 doublereal PureFluidPhase::
153 {
154  setTPXState();
155  doublereal s = m_sub->s() * m_mw;
156  check(s);
157  return s;
158 }
159 
160 doublereal PureFluidPhase::
161 gibbs_mole() const
162 {
163  setTPXState();
164  doublereal g = m_sub->g() * m_mw;
165  check(g);
166  return g;
167 }
168 
169 doublereal PureFluidPhase::
170 cp_mole() const
171 {
172  setTPXState();
173  doublereal cp = m_sub->cp() * m_mw;
174  check(cp);
175  return cp;
176 }
177 
178 doublereal PureFluidPhase::
179 cv_mole() const
180 {
181  setTPXState();
182  doublereal cv = m_sub->cv() * m_mw;
183  check(cv);
184  return cv;
185 }
186 
187 doublereal PureFluidPhase::
188 pressure() const
189 {
190  setTPXState();
191  doublereal p = m_sub->P();
192  check(p);
193  return p;
194 }
195 //====================================================================================================================
196 void PureFluidPhase::
197 setPressure(doublereal p)
198 {
199  Set(tpx::TP, temperature(), p);
200  setDensity(1.0/m_sub->v());
201  check();
202 }
203 //====================================================================================================================
204 void PureFluidPhase::Set(int n, double x, double y) const
205 {
206  try {
207  m_sub->Set(n, x, y);
208  } catch (tpx::TPX_Error) {
209  reportTPXError();
210  }
211 }
212 //====================================================================================================================
214 {
215  Set(tpx::TV, temperature(), 1.0/density());
216 }
217 //====================================================================================================================
218 void PureFluidPhase::check(doublereal v) const
219 {
220  if (m_sub->Error() || v == tpx::Undef) {
221  throw CanteraError("PureFluidPhase",string(tpx::errorMsg(
222  m_sub->Error())));
223  }
224 }
225 //====================================================================================================================
227 {
228  string msg = tpx::TPX_Error::ErrorMessage;
229  string proc = "tpx::"+tpx::TPX_Error::ErrorProcedure;
230  throw CanteraError(proc,msg);
231 }
232 //====================================================================================================================
233 
235 {
236  return m_sub->isothermalCompressibility();
237 }
238 //====================================================================================================================
240 {
241  return m_sub->thermalExpansionCoeff();
242 }
243 //====================================================================================================================
245 {
246  return *m_sub;
247 }
248 //====================================================================================================================
249 // Returns an array of partial molar enthalpies for the species
250 // in the mixture. Units (J/kmol)
251 /*
252  * @param hbar Output vector of species partial molar enthalpies.
253  * Length: m_kk. units are J/kmol.
254  */
255 void PureFluidPhase::getPartialMolarEnthalpies(doublereal* hbar) const
256 {
257  hbar[0] = enthalpy_mole();
258 }
259 //====================================================================================================================
260 // Returns an array of partial molar entropies of the species in the
261 // solution. Units: J/kmol/K.
262 /*
263  * @param sbar Output vector of species partial molar entropies.
264  * Length = m_kk. units are J/kmol/K.
265  */
266 void PureFluidPhase::getPartialMolarEntropies(doublereal* sbar) const
267 {
268  sbar[0] = entropy_mole();
269 }
270 //====================================================================================================================
271 // Return an array of partial molar internal energies for the
272 // species in the mixture. Units: J/kmol.
273 /*
274  * @param ubar Output vector of species partial molar internal energies.
275  * Length = m_kk. units are J/kmol.
276  */
277 void PureFluidPhase::getPartialMolarIntEnergies(doublereal* ubar) const
278 {
279  ubar[0] = intEnergy_mole();
280 }
281 //====================================================================================================================
282 // Return an array of partial molar heat capacities for the
283 // species in the mixture. Units: J/kmol/K
284 /*
285  * @param cpbar Output vector of species partial molar heat
286  * capacities at constant pressure.
287  * Length = m_kk. units are J/kmol/K.
288  */
289 void PureFluidPhase::getPartialMolarCp(doublereal* cpbar) const
290 {
291  cpbar[0] = cp_mole();
292 }
293 //====================================================================================================================
294 // Return an array of partial molar volumes for the
295 // species in the mixture. Units: m^3/kmol.
296 /*
297  * @param vbar Output vector of species partial molar volumes.
298  * Length = m_kk. units are m^3/kmol.
299  */
300 void PureFluidPhase::getPartialMolarVolumes(doublereal* vbar) const
301 {
302  vbar[0] = 1.0 / molarDensity();
303 }
304 //====================================================================================================================
306 {
308 }
309 //====================================================================================================================
311 {
312  c[0] = 1.0;
313 }
314 //====================================================================================================================
315 doublereal PureFluidPhase::standardConcentration(size_t k) const
316 {
317  return 1.0;
318 }
319 //====================================================================================================================
320 void PureFluidPhase::getActivities(doublereal* a) const
321 {
322  a[0] = 1.0;
323 }
324 //====================================================================================================================
325 // Get the array of chemical potentials at unit activity for the species
326 // at their standard states at the current <I>T</I> and <I>P</I> of the solution.
327 /*
328  * These are the standard state chemical potentials \f$ \mu^0_k(T,P)
329  * \f$. The values are evaluated at the current
330  * temperature and pressure of the solution
331  *
332  * @param mu Output vector of chemical potentials.
333  * Length: m_kk.
334  */
336 {
337  mu[0] = gibbs_mole();
338 }
339 //====================================================================================================================
340 // Get the nondimensional Enthalpy functions for the species
341 // at their standard states at the current <I>T</I> and <I>P</I> of the solution.
342 /*
343  * @param hrt Output vector of nondimensional standard state enthalpies.
344  * Length: m_kk.
345  */
346 void PureFluidPhase::getEnthalpy_RT(doublereal* hrt) const
347 {
348  doublereal rt = _RT();
349  doublereal h = enthalpy_mole();
350  hrt[0] = h / rt;
351 }
352 //====================================================================================================================
353 // Get the array of nondimensional Entropy functions for the
354 // standard state species at the current <I>T</I> and <I>P</I> of the solution.
355 /*
356  * @param sr Output vector of nondimensional standard state entropies.
357  * Length: m_kk.
358  */
359 void PureFluidPhase::getEntropy_R(doublereal* sr) const
360 {
361  doublereal s = entropy_mole();
362  sr[0] = s / GasConstant;
363 }
364 //====================================================================================================================
365 // Get the nondimensional Gibbs functions for the species
366 // in their standard states at the current <I>T</I> and <I>P</I> of the solution.
367 /*
368  * @param grt Output vector of nondimensional standard state gibbs free energies
369  * Length: m_kk.
370  */
371 void PureFluidPhase::getGibbs_RT(doublereal* grt) const
372 {
373  doublereal rt = _RT();
374  doublereal g = gibbs_mole();
375  grt[0] = g / rt;
376 }
377 //====================================================================================================================
378 // Returns the vector of nondimensional enthalpies of the reference state at the current temperature
379 // of the solution and the reference pressure for the species.
380 /*
381  * This base function will throw a CanteraException unless
382  * it is overwritten in a derived class.
383  *
384  * @param hrt Output vector containing the nondimensional reference state enthalpies
385  * Length: m_kk.
386  */
387 void PureFluidPhase::getEnthalpy_RT_ref(doublereal* hrt) const
388 {
389  double psave = pressure();
390  double t = temperature();
391  //double pref = m_spthermo->refPressure();
392  double plow = 1.0E-8;
393  Set(tpx::TP, t, plow);
394  getEnthalpy_RT(hrt);
395  Set(tpx::TP, t, psave);
396 
397 }
398 //====================================================================================================================
399 // Returns the vector of nondimensional Gibbs Free Energies of the reference state at the current temperature
400 // of the solution and the reference pressure for the species.
401 /*
402  * @param grt Output vector containing the nondimensional reference state
403  * Gibbs Free energies. Length: m_kk.
404  */
405 void PureFluidPhase::getGibbs_RT_ref(doublereal* grt) const
406 {
407  double psave = pressure();
408  double t = temperature();
409  double pref = m_spthermo->refPressure();
410  double plow = 1.0E-8;
411  Set(tpx::TP, t, plow);
412  getGibbs_RT(grt);
413  grt[0] += log(pref/plow);
414  Set(tpx::TP, t, psave);
415 }
416 //====================================================================================================================
417 // Returns the vector of the gibbs function of the reference state at the current temperature
418 // of the solution and the reference pressure for the species.
419 /*
420  * units = J/kmol
421  *
422  * @param g Output vector containing the reference state
423  * Gibbs Free energies. Length: m_kk. Units: J/kmol.
424  */
425 void PureFluidPhase::getGibbs_ref(doublereal* g) const
426 {
427  getGibbs_RT_ref(g);
428  g[0] *= (GasConstant * temperature());
429 }
430 //====================================================================================================================
431 // Returns the vector of nondimensional entropies of the reference state at the current temperature
432 // of the solution and the reference pressure for each species.
433 /*
434  * @param er Output vector containing the nondimensional reference state
435  * entropies. Length: m_kk.
436  */
437 void PureFluidPhase::getEntropy_R_ref(doublereal* er) const
438 {
439  double psave = pressure();
440  double t = temperature();
441  double pref = m_spthermo->refPressure();
442  double plow = 1.0E-8;
443  Set(tpx::TP, t, plow);
444  getEntropy_R(er);
445  er[0] -= log(pref/plow);
446  Set(tpx::TP, t, psave);
447 }
448 //====================================================================================================================
449 // critical temperature
451 {
452  return m_sub->Tcrit();
453 }
454 //====================================================================================================================
455 /// critical pressure
457 {
458  return m_sub->Pcrit();
459 }
460 //====================================================================================================================
461 /// critical density
462 doublereal PureFluidPhase::critDensity() const
463 {
464  return 1.0/m_sub->Vcrit();
465 }
466 //====================================================================================================================
467 
468 /// saturation temperature
469 doublereal PureFluidPhase::satTemperature(doublereal p) const
470 {
471  try {
472  doublereal ts = m_sub->Tsat(p);
473  return ts;
474  } catch (tpx::TPX_Error) {
475  reportTPXError();
476  return -1.0;
477  }
478 }
479 //====================================================================================================================
480 void PureFluidPhase::setState_HP(doublereal h, doublereal p,
481  doublereal tol)
482 {
483  Set(tpx::HP, h, p);
484  setState_TR(m_sub->Temp(), 1.0/m_sub->v());
485  check();
486 }
487 //====================================================================================================================
488 void PureFluidPhase::setState_UV(doublereal u, doublereal v,
489  doublereal tol)
490 {
491  Set(tpx::UV, u, v);
492  setState_TR(m_sub->Temp(), 1.0/m_sub->v());
493  check();
494 }
495 //====================================================================================================================
496 void PureFluidPhase::setState_SV(doublereal s, doublereal v,
497  doublereal tol)
498 {
499  Set(tpx::SV, s, v);
500  setState_TR(m_sub->Temp(), 1.0/m_sub->v());
501  check();
502 }
503 //====================================================================================================================
504 void PureFluidPhase::setState_SP(doublereal s, doublereal p,
505  doublereal tol)
506 {
507  Set(tpx::SP, s, p);
508  setState_TR(m_sub->Temp(), 1.0/m_sub->v());
509  check();
510 }
511 //====================================================================================================================
512 // saturation pressure
513 doublereal PureFluidPhase::satPressure(doublereal t) const
514 {
515  doublereal vsv = m_sub->v();
516  try {
517  Set(tpx::TV,t,vsv);
518  doublereal ps = m_sub->Ps();
519  return ps;
520  } catch (tpx::TPX_Error) {
521  reportTPXError();
522  return -1.0;
523  }
524 }
525 //====================================================================================================================
527 {
528  setTPXState();
529  doublereal x = m_sub->x();
530  check(x);
531  return x;
532 }
533 //====================================================================================================================
534 void PureFluidPhase::setState_Tsat(doublereal t, doublereal x)
535 {
536  setTemperature(t);
537  setTPXState();
538  Set(tpx::TX, t, x);
539  setDensity(1.0/m_sub->v());
540  check();
541 }
542 //====================================================================================================================
543 void PureFluidPhase::setState_Psat(doublereal p, doublereal x)
544 {
545  setTPXState();
546  Set(tpx::PX, p, x);
547  setTemperature(m_sub->Temp());
548  setDensity(1.0/m_sub->v());
549  check();
550 }
551 
552 //====================================================================================================================
553 /**
554  * Format a summary of the mixture state for output.
555  */
556 std::string PureFluidPhase::report(bool show_thermo) const
557 {
558 
559 
560  char p[800];
561  string s = "";
562  try {
563  if (name() != "") {
564  sprintf(p, " \n %s:\n", name().c_str());
565  s += p;
566  }
567  sprintf(p, " \n temperature %12.6g K\n", temperature());
568  s += p;
569  sprintf(p, " pressure %12.6g Pa\n", pressure());
570  s += p;
571  sprintf(p, " density %12.6g kg/m^3\n", density());
572  s += p;
573  sprintf(p, " mean mol. weight %12.6g amu\n", meanMolecularWeight());
574  s += p;
575 
576  if (eosType() == cPureFluid) {
577  double xx = ((PureFluidPhase*)(this))->vaporFraction();
578  sprintf(p, " vapor fraction %12.6g \n",
579  xx); //th.vaporFraction());
580  s += p;
581  }
582 
583  doublereal phi = electricPotential();
584  if (phi != 0.0) {
585  sprintf(p, " potential %12.6g V\n", phi);
586  s += p;
587  }
588  if (show_thermo) {
589  sprintf(p, " \n");
590  s += p;
591  sprintf(p, " 1 kg 1 kmol\n");
592  s += p;
593  sprintf(p, " ----------- ------------\n");
594  s += p;
595  sprintf(p, " enthalpy %12.6g %12.4g J\n",
597  s += p;
598  sprintf(p, " internal energy %12.6g %12.4g J\n",
600  s += p;
601  sprintf(p, " entropy %12.6g %12.4g J/K\n",
603  s += p;
604  sprintf(p, " Gibbs function %12.6g %12.4g J\n",
605  gibbs_mass(), gibbs_mole());
606  s += p;
607  sprintf(p, " heat capacity c_p %12.6g %12.4g J/K\n",
608  cp_mass(), cp_mole());
609  s += p;
610  try {
611  sprintf(p, " heat capacity c_v %12.6g %12.4g J/K\n",
612  cv_mass(), cv_mole());
613  s += p;
614  } catch (CanteraError& err) {
615  err.save();
616  sprintf(p, " heat capacity c_v <not implemented> \n");
617  s += p;
618  }
619  }
620 
621  size_t kk = nSpecies();
622  vector_fp x(kk);
623  vector_fp y(kk);
624  vector_fp mu(kk);
625  getMoleFractions(&x[0]);
626  getMassFractions(&y[0]);
627  getChemPotentials(&mu[0]);
628  doublereal rt = GasConstant * temperature();
629  //if (th.nSpecies() > 1) {
630 
631  if (show_thermo) {
632  sprintf(p, " \n X "
633  " Y Chem. Pot. / RT \n");
634  s += p;
635  sprintf(p, " ------------- "
636  "------------ ------------\n");
637  s += p;
638  for (size_t k = 0; k < kk; k++) {
639  if (x[k] > SmallNumber) {
640  sprintf(p, "%18s %12.6g %12.6g %12.6g\n",
641  speciesName(k).c_str(), x[k], y[k], mu[k]/rt);
642  } else {
643  sprintf(p, "%18s %12.6g %12.6g \n",
644  speciesName(k).c_str(), x[k], y[k]);
645  }
646  s += p;
647  }
648  } else {
649  sprintf(p, " \n X"
650  "Y\n");
651  s += p;
652  sprintf(p, " -------------"
653  " ------------\n");
654  s += p;
655  for (size_t k = 0; k < kk; k++) {
656  sprintf(p, "%18s %12.6g %12.6g\n",
657  speciesName(k).c_str(), x[k], y[k]);
658  s += p;
659  }
660  }
661  }
662  //}
663  catch (CanteraError& err) {
664  err.save();
665  }
666  return s;
667 }
668 //====================================================================================================================
669 /*
670  * Format a summary of the mixture state for output.
671  */
672 void PureFluidPhase::reportCSV(std::ofstream& csvFile) const
673 {
674 
675 
676  csvFile.precision(3);
677  int tabS = 15;
678  int tabM = 30;
679  int tabL = 40;
680  try {
681  if (name() != "") {
682  csvFile << "\n"+name()+"\n\n";
683  }
684  csvFile << setw(tabL) << "temperature (K) =" << setw(tabS) << temperature() << endl;
685  csvFile << setw(tabL) << "pressure (Pa) =" << setw(tabS) << pressure() << endl;
686  csvFile << setw(tabL) << "density (kg/m^3) =" << setw(tabS) << density() << endl;
687  csvFile << setw(tabL) << "mean mol. weight (amu) =" << setw(tabS) << meanMolecularWeight() << endl;
688  csvFile << setw(tabL) << "potential (V) =" << setw(tabS) << electricPotential() << endl;
689  if (eosType() == cPureFluid) {
690  double xx = ((PureFluidPhase*)(this))->vaporFraction();
691  csvFile << setw(tabL) << "vapor fraction = " << setw(tabS) << xx << endl;
692  }
693  csvFile << endl;
694 
695  csvFile << setw(tabL) << "enthalpy (J/kg) = " << setw(tabS) << enthalpy_mass() << setw(tabL) << "enthalpy (J/kmol) = " << setw(tabS) << enthalpy_mole() << endl;
696  csvFile << setw(tabL) << "internal E (J/kg) = " << setw(tabS) << intEnergy_mass() << setw(tabL) << "internal E (J/kmol) = " << setw(tabS) << intEnergy_mole() << endl;
697  csvFile << setw(tabL) << "entropy (J/kg) = " << setw(tabS) << entropy_mass() << setw(tabL) << "entropy (J/kmol) = " << setw(tabS) << entropy_mole() << endl;
698  csvFile << setw(tabL) << "Gibbs (J/kg) = " << setw(tabS) << gibbs_mass() << setw(tabL) << "Gibbs (J/kmol) = " << setw(tabS) << gibbs_mole() << endl;
699  csvFile << setw(tabL) << "heat capacity c_p (J/K/kg) = " << setw(tabS) << cp_mass() << setw(tabL) << "heat capacity c_p (J/K/kmol) = " << setw(tabS) << cp_mole() << endl;
700  csvFile << setw(tabL) << "heat capacity c_v (J/K/kg) = " << setw(tabS) << cv_mass() << setw(tabL) << "heat capacity c_v (J/K/kmol) = " << setw(tabS) << cv_mole() << endl;
701 
702  csvFile.precision(8);
703 
704  size_t kk = nSpecies();
705  std::vector<double> x(kk, 0.0);
706  std::vector<double> y(kk, 0.0);
707  std::vector<double> mu(kk, 0.0);
708  std::vector<double> a(kk, 0.0);
709  std::vector<double> ac(kk, 0.0);
710  std::vector<double> hbar(kk, 0.0);
711  std::vector<double> sbar(kk, 0.0);
712  std::vector<double> ubar(kk, 0.0);
713  std::vector<double> cpbar(kk, 0.0);
714  std::vector<double> vbar(kk, 0.0);
715  std::vector<std::string> pNames;
716  std::vector<std::vector<double> > data;
717 
718  getMoleFractions(&x[0]);
719  pNames.push_back("X");
720  data.push_back(x);
721  try {
722  getMassFractions(&y[0]);
723  pNames.push_back("Y");
724  data.push_back(y);
725  } catch (CanteraError& err) {
726  err.save();
727  }
728  try {
729  getChemPotentials(&mu[0]);
730  pNames.push_back("Chem. Pot (J/kmol)");
731  data.push_back(mu);
732  } catch (CanteraError& err) {
733  err.save();
734  }
735  try {
736  getActivities(&a[0]);
737  pNames.push_back("Activity");
738  data.push_back(a);
739  } catch (CanteraError& err) {
740  err.save();
741  }
742  try {
743  getActivityCoefficients(&ac[0]);
744  pNames.push_back("Act. Coeff.");
745  data.push_back(ac);
746  } catch (CanteraError& err) {
747  err.save();
748  }
749  try {
750  getPartialMolarEnthalpies(&hbar[0]);
751  pNames.push_back("Part. Mol Enthalpy (J/kmol)");
752  data.push_back(hbar);
753  } catch (CanteraError& err) {
754  err.save();
755  }
756  try {
757  getPartialMolarEntropies(&sbar[0]);
758  pNames.push_back("Part. Mol. Entropy (J/K/kmol)");
759  data.push_back(sbar);
760  } catch (CanteraError& err) {
761  err.save();
762  }
763  try {
764  getPartialMolarIntEnergies(&ubar[0]);
765  pNames.push_back("Part. Mol. Energy (J/kmol)");
766  data.push_back(ubar);
767  } catch (CanteraError& err) {
768  err.save();
769  }
770  try {
771  getPartialMolarCp(&cpbar[0]);
772  pNames.push_back("Part. Mol. Cp (J/K/kmol");
773  data.push_back(cpbar);
774  } catch (CanteraError& err) {
775  err.save();
776  }
777  try {
778  getPartialMolarVolumes(&vbar[0]);
779  pNames.push_back("Part. Mol. Cv (J/K/kmol)");
780  data.push_back(vbar);
781  } catch (CanteraError& err) {
782  err.save();
783  }
784 
785  csvFile << endl << setw(tabS) << "Species,";
786  for (int i = 0; i < (int)pNames.size(); i++) {
787  csvFile << setw(tabM) << pNames[i] << ",";
788  }
789  csvFile << endl;
790  /*
791  csvFile.fill('-');
792  csvFile << setw(tabS+(tabM+1)*pNames.size()) << "-\n";
793  csvFile.fill(' ');
794  */
795  for (size_t k = 0; k < kk; k++) {
796  csvFile << setw(tabS) << speciesName(k) + ",";
797  if (x[k] > SmallNumber) {
798  for (int i = 0; i < (int)pNames.size(); i++) {
799  csvFile << setw(tabM) << data[i][k] << ",";
800  }
801  csvFile << endl;
802  } else {
803  for (int i = 0; i < (int)pNames.size(); i++) {
804  csvFile << setw(tabM) << 0 << ",";
805  }
806  csvFile << endl;
807  }
808  }
809  } catch (CanteraError& err) {
810  err.save();
811  }
812 }
813 }