Cantera  2.5.1
ThermoPhase.cpp
Go to the documentation of this file.
1 /**
2  * @file ThermoPhase.cpp
3  * Definition file for class ThermoPhase, the base class for phases with
4  * thermodynamic properties
5  * (see class \link Cantera::ThermoPhase ThermoPhase\endlink).
6  */
7 
8 // This file is part of Cantera. See License.txt in the top-level directory or
9 // at https://cantera.org/license.txt for license and copyright information.
10 
17 #include "cantera/base/ctml.h"
18 
19 #include <iomanip>
20 #include <fstream>
21 
22 using namespace std;
23 
24 namespace Cantera
25 {
26 
27 ThermoPhase::ThermoPhase() :
28  m_speciesData(0),
29  m_phi(0.0),
30  m_chargeNeutralityNecessary(false),
31  m_ssConvention(cSS_CONVENTION_TEMPERATURE),
32  m_tlast(0.0)
33 {
34 }
35 
36 ThermoPhase::~ThermoPhase()
37 {
38  for (size_t k = 0; k < m_speciesData.size(); k++) {
39  delete m_speciesData[k];
40  }
41 }
42 
43 void ThermoPhase::resetHf298(size_t k) {
44  if (k != npos) {
46  } else {
47  for (size_t k = 0; k < nSpecies(); k++) {
49  }
50  }
52 }
53 
55 {
56  return cAC_CONVENTION_MOLAR;
57 }
58 
60 {
61  return m_ssConvention;
62 }
63 
65 {
66  // kmol/m^3 for bulk phases, kmol/m^2 for surface phases, etc.
67  return Units(1.0, 0, -static_cast<double>(nDim()), 0, 0, 0, 1);
68 }
69 
70 doublereal ThermoPhase::logStandardConc(size_t k) const
71 {
72  return log(standardConcentration(k));
73 }
74 
75 void ThermoPhase::getActivities(doublereal* a) const
76 {
78  for (size_t k = 0; k < nSpecies(); k++) {
79  a[k] /= standardConcentration(k);
80  }
81 }
82 
83 void ThermoPhase::getLnActivityCoefficients(doublereal* lnac) const
84 {
86  for (size_t k = 0; k < m_kk; k++) {
87  lnac[k] = std::log(lnac[k]);
88  }
89 }
90 
91 void ThermoPhase::getElectrochemPotentials(doublereal* mu) const
92 {
94  double ve = Faraday * electricPotential();
95  for (size_t k = 0; k < m_kk; k++) {
96  mu[k] += ve*charge(k);
97  }
98 }
99 
100 void ThermoPhase::setState_TPX(doublereal t, doublereal p, const doublereal* x)
101 {
102  setMoleFractions(x);
103  setState_TP(t,p);
104 }
105 
106 void ThermoPhase::setState_TPX(doublereal t, doublereal p, const compositionMap& x)
107 {
109  setState_TP(t,p);
110 }
111 
112 void ThermoPhase::setState_TPX(doublereal t, doublereal p, const std::string& x)
113 {
115  setState_TP(t,p);
116 }
117 
118 void ThermoPhase::setState_TPY(doublereal t, doublereal p, const doublereal* y)
119 {
120  setMassFractions(y);
121  setState_TP(t,p);
122 }
123 
124 void ThermoPhase::setState_TPY(doublereal t, doublereal p, const compositionMap& y)
125 {
127  setState_TP(t,p);
128 }
129 
130 void ThermoPhase::setState_TPY(doublereal t, doublereal p, const std::string& y)
131 {
133  setState_TP(t,p);
134 }
135 
136 void ThermoPhase::setState_TP(doublereal t, doublereal p)
137 {
138  double tsave = temperature();
139  double dsave = density();
140  try {
141  setTemperature(t);
142  setPressure(p);
143  } catch (CanteraError&) {
144  setState_TR(tsave, dsave);
145  throw;
146  }
147 }
148 
149 void ThermoPhase::setState_RPX(doublereal rho, doublereal p, const doublereal* x)
150 {
151  setMoleFractions(x);
152  setState_RP(rho, p);
153 }
154 
155 void ThermoPhase::setState_RPX(doublereal rho, doublereal p, const compositionMap& x)
156 {
158  setState_RP(rho,p);
159 }
160 
161 void ThermoPhase::setState_RPX(doublereal rho, doublereal p, const std::string& x)
162 {
164  setState_RP(rho,p);
165 }
166 
167 void ThermoPhase::setState_RPY(doublereal rho, doublereal p, const doublereal* y)
168 {
169  setMassFractions(y);
170  setState_RP(rho,p);
171 }
172 
173 void ThermoPhase::setState_RPY(doublereal rho, doublereal p, const compositionMap& y)
174 {
176  setState_RP(rho,p);
177 }
178 
179 void ThermoPhase::setState_RPY(doublereal rho, doublereal p, const std::string& y)
180 {
182  setState_RP(rho,p);
183 }
184 
185 void ThermoPhase::setState_PX(doublereal p, doublereal* x)
186 {
187  setMoleFractions(x);
188  setPressure(p);
189 }
190 
191 void ThermoPhase::setState_PY(doublereal p, doublereal* y)
192 {
193  setMassFractions(y);
194  setPressure(p);
195 }
196 
197 void ThermoPhase::setState_HP(double Htarget, double p, double rtol)
198 {
199  setState_HPorUV(Htarget, p, rtol, false);
200 }
201 
202 void ThermoPhase::setState_UV(double u, double v, double rtol)
203 {
204  assertCompressible("setState_UV");
205  setState_HPorUV(u, v, rtol, true);
206 }
207 
208 void ThermoPhase::setState(const AnyMap& input_state)
209 {
210  AnyMap state = input_state;
211 
212  // Remap allowable synonyms
213  if (state.hasKey("mass-fractions")) {
214  state["Y"] = state["mass-fractions"];
215  state.erase("mass-fractions");
216  }
217  if (state.hasKey("mole-fractions")) {
218  state["X"] = state["mole-fractions"];
219  state.erase("mole-fractions");
220  }
221  if (state.hasKey("temperature")) {
222  state["T"] = state["temperature"];
223  }
224  if (state.hasKey("pressure")) {
225  state["P"] = state["pressure"];
226  }
227  if (state.hasKey("enthalpy")) {
228  state["H"] = state["enthalpy"];
229  }
230  if (state.hasKey("int-energy")) {
231  state["U"] = state["int-energy"];
232  }
233  if (state.hasKey("internal-energy")) {
234  state["U"] = state["internal-energy"];
235  }
236  if (state.hasKey("specific-volume")) {
237  state["V"] = state["specific-volume"];
238  }
239  if (state.hasKey("entropy")) {
240  state["S"] = state["entropy"];
241  }
242  if (state.hasKey("density")) {
243  state["D"] = state["density"];
244  }
245  if (state.hasKey("vapor-fraction")) {
246  state["Q"] = state["vapor-fraction"];
247  }
248 
249  // Set composition
250  if (state.hasKey("X")) {
251  if (state["X"].is<string>()) {
252  setMoleFractionsByName(state["X"].asString());
253  } else {
254  setMoleFractionsByName(state["X"].asMap<double>());
255  }
256  state.erase("X");
257  } else if (state.hasKey("Y")) {
258  if (state["Y"].is<string>()) {
259  setMassFractionsByName(state["Y"].asString());
260  } else {
261  setMassFractionsByName(state["Y"].asMap<double>());
262  }
263  state.erase("Y");
264  }
265  // set thermodynamic state using whichever property set is found
266  if (state.size() == 0) {
267  setState_TP(298.15, OneAtm);
268  } else if (state.hasKey("T") && state.hasKey("P")) {
269  double T = state.convert("T", "K");
270  double P = state.convert("P", "Pa");
271  if (state.hasKey("Q")) {
272  setState_TPQ(T, P, state["Q"].asDouble());
273  } else {
274  setState_TP(T, P);
275  }
276  } else if (state.hasKey("T") && state.hasKey("D")) {
277  setState_TR(state.convert("T", "K"), state.convert("D", "kg/m^3"));
278  } else if (state.hasKey("T") && state.hasKey("V")) {
279  setState_TV(state.convert("T", "K"), state.convert("V", "m^3/kg"));
280  } else if (state.hasKey("H") && state.hasKey("P")) {
281  setState_HP(state.convert("H", "J/kg"), state.convert("P", "Pa"));
282  } else if (state.hasKey("U") && state.hasKey("V")) {
283  setState_UV(state.convert("U", "J/kg"), state.convert("V", "m^3/kg"));
284  } else if (state.hasKey("S") && state.hasKey("P")) {
285  setState_SP(state.convert("S", "J/kg/K"), state.convert("P", "Pa"));
286  } else if (state.hasKey("S") && state.hasKey("V")) {
287  setState_SV(state.convert("S", "J/kg/K"), state.convert("V", "m^3/kg"));
288  } else if (state.hasKey("S") && state.hasKey("T")) {
289  setState_ST(state.convert("S", "J/kg/K"), state.convert("T", "K"));
290  } else if (state.hasKey("P") && state.hasKey("V")) {
291  setState_PV(state.convert("P", "Pa"), state.convert("V", "m^3/kg"));
292  } else if (state.hasKey("U") && state.hasKey("P")) {
293  setState_UP(state.convert("U", "J/kg"), state.convert("P", "Pa"));
294  } else if (state.hasKey("V") && state.hasKey("H")) {
295  setState_VH(state.convert("V", "m^3/kg"), state.convert("H", "J/kg"));
296  } else if (state.hasKey("T") && state.hasKey("H")) {
297  setState_TH(state.convert("T", "K"), state.convert("H", "J/kg"));
298  } else if (state.hasKey("S") && state.hasKey("H")) {
299  setState_SH(state.convert("S", "J/kg/K"), state.convert("H", "J/kg"));
300  } else if (state.hasKey("D") && state.hasKey("P")) {
301  setState_RP(state.convert("D", "kg/m^3"), state.convert("P", "Pa"));
302  } else if (state.hasKey("P") && state.hasKey("Q")) {
303  setState_Psat(state.convert("P", "Pa"), state["Q"].asDouble());
304  } else if (state.hasKey("T") && state.hasKey("Q")) {
305  setState_Tsat(state.convert("T", "K"), state["Q"].asDouble());
306  } else if (state.hasKey("T")) {
307  setState_TP(state.convert("T", "K"), OneAtm);
308  } else if (state.hasKey("P")) {
309  setState_TP(298.15, state.convert("P", "Pa"));
310  } else {
311  throw CanteraError("ThermoPhase::setState",
312  "'state' did not specify a recognized set of properties.\n"
313  "Keys provided were: {}", input_state.keys_str());
314  }
315 }
316 
317 void ThermoPhase::setState_conditional_TP(doublereal t, doublereal p, bool set_p)
318 {
319  setTemperature(t);
320  if (set_p) {
321  setPressure(p);
322  }
323 }
324 
325 void ThermoPhase::setState_HPorUV(double Htarget, double p,
326  double rtol, bool doUV)
327 {
328  doublereal dt;
329  doublereal v = 0.0;
330 
331  // Assign the specific volume or pressure and make sure it's positive
332  if (doUV) {
333  doublereal v = p;
334  if (v < 1.0E-300) {
335  throw CanteraError("ThermoPhase::setState_HPorUV (UV)",
336  "Input specific volume is too small or negative. v = {}", v);
337  }
338  setDensity(1.0/v);
339  } else {
340  if (p < 1.0E-300) {
341  throw CanteraError("ThermoPhase::setState_HPorUV (HP)",
342  "Input pressure is too small or negative. p = {}", p);
343  }
344  setPressure(p);
345  }
346  double Tmax = maxTemp() + 0.1;
347  double Tmin = minTemp() - 0.1;
348 
349  // Make sure we are within the temperature bounds at the start
350  // of the iteration
351  double Tnew = temperature();
352  double Tinit = Tnew;
353  if (Tnew > Tmax) {
354  Tnew = Tmax - 1.0;
355  } else if (Tnew < Tmin) {
356  Tnew = Tmin + 1.0;
357  }
358  if (Tnew != Tinit) {
359  setState_conditional_TP(Tnew, p, !doUV);
360  }
361 
362  double Hnew = (doUV) ? intEnergy_mass() : enthalpy_mass();
363  double Cpnew = (doUV) ? cv_mass() : cp_mass();
364  double Htop = Hnew;
365  double Ttop = Tnew;
366  double Hbot = Hnew;
367  double Tbot = Tnew;
368 
369  bool ignoreBounds = false;
370  // Unstable phases are those for which cp < 0.0. These are possible for
371  // cases where we have passed the spinodal curve.
372  bool unstablePhase = false;
373  // Counter indicating the last temperature point where the
374  // phase was unstable
375  double Tunstable = -1.0;
376  bool unstablePhaseNew = false;
377 
378  // Newton iteration
379  for (int n = 0; n < 500; n++) {
380  double Told = Tnew;
381  double Hold = Hnew;
382  double cpd = Cpnew;
383  if (cpd < 0.0) {
384  unstablePhase = true;
385  Tunstable = Tnew;
386  }
387  // limit step size to 100 K
388  dt = clip((Htarget - Hold)/cpd, -100.0, 100.0);
389 
390  // Calculate the new T
391  Tnew = Told + dt;
392 
393  // Limit the step size so that we are convergent This is the step that
394  // makes it different from a Newton's algorithm
395  if ((dt > 0.0 && unstablePhase) || (dt <= 0.0 && !unstablePhase)) {
396  if (Hbot < Htarget && Tnew < (0.75 * Tbot + 0.25 * Told)) {
397  dt = 0.75 * (Tbot - Told);
398  Tnew = Told + dt;
399  }
400  } else if (Htop > Htarget && Tnew > (0.75 * Ttop + 0.25 * Told)) {
401  dt = 0.75 * (Ttop - Told);
402  Tnew = Told + dt;
403  }
404 
405  // Check Max and Min values
406  if (Tnew > Tmax && !ignoreBounds) {
407  setState_conditional_TP(Tmax, p, !doUV);
408  double Hmax = (doUV) ? intEnergy_mass() : enthalpy_mass();
409  if (Hmax >= Htarget) {
410  if (Htop < Htarget) {
411  Ttop = Tmax;
412  Htop = Hmax;
413  }
414  } else {
415  Tnew = Tmax + 1.0;
416  ignoreBounds = true;
417  }
418  }
419  if (Tnew < Tmin && !ignoreBounds) {
420  setState_conditional_TP(Tmin, p, !doUV);
421  double Hmin = (doUV) ? intEnergy_mass() : enthalpy_mass();
422  if (Hmin <= Htarget) {
423  if (Hbot > Htarget) {
424  Tbot = Tmin;
425  Hbot = Hmin;
426  }
427  } else {
428  Tnew = Tmin - 1.0;
429  ignoreBounds = true;
430  }
431  }
432 
433  // Try to keep phase within its region of stability
434  // -> Could do a lot better if I calculate the
435  // spinodal value of H.
436  for (int its = 0; its < 10; its++) {
437  Tnew = Told + dt;
438  if (Tnew < Told / 3.0) {
439  Tnew = Told / 3.0;
440  dt = -2.0 * Told / 3.0;
441  }
442  setState_conditional_TP(Tnew, p, !doUV);
443  if (doUV) {
444  Hnew = intEnergy_mass();
445  Cpnew = cv_mass();
446  } else {
447  Hnew = enthalpy_mass();
448  Cpnew = cp_mass();
449  }
450  if (Cpnew < 0.0) {
451  unstablePhaseNew = true;
452  Tunstable = Tnew;
453  } else {
454  unstablePhaseNew = false;
455  break;
456  }
457  if (unstablePhase == false && unstablePhaseNew == true) {
458  dt *= 0.25;
459  }
460  }
461 
462  if (Hnew == Htarget) {
463  return;
464  } else if (Hnew > Htarget && (Htop < Htarget || Hnew < Htop)) {
465  Htop = Hnew;
466  Ttop = Tnew;
467  } else if (Hnew < Htarget && (Hbot > Htarget || Hnew > Hbot)) {
468  Hbot = Hnew;
469  Tbot = Tnew;
470  }
471  // Convergence in H
472  double Herr = Htarget - Hnew;
473  double acpd = std::max(fabs(cpd), 1.0E-5);
474  double denom = std::max(fabs(Htarget), acpd * Tnew);
475  double HConvErr = fabs((Herr)/denom);
476  if (HConvErr < rtol || fabs(dt/Tnew) < rtol) {
477  return;
478  }
479  }
480  // We are here when there hasn't been convergence
481 
482  // Formulate a detailed error message, since questions seem to arise often
483  // about the lack of convergence.
484  string ErrString = "No convergence in 500 iterations\n";
485  if (doUV) {
486  ErrString += fmt::format(
487  "\tTarget Internal Energy = {}\n"
488  "\tCurrent Specific Volume = {}\n"
489  "\tStarting Temperature = {}\n"
490  "\tCurrent Temperature = {}\n"
491  "\tCurrent Internal Energy = {}\n"
492  "\tCurrent Delta T = {}\n",
493  Htarget, v, Tinit, Tnew, Hnew, dt);
494  } else {
495  ErrString += fmt::format(
496  "\tTarget Enthalpy = {}\n"
497  "\tCurrent Pressure = {}\n"
498  "\tStarting Temperature = {}\n"
499  "\tCurrent Temperature = {}\n"
500  "\tCurrent Enthalpy = {}\n"
501  "\tCurrent Delta T = {}\n",
502  Htarget, p, Tinit, Tnew, Hnew, dt);
503  }
504  if (unstablePhase) {
505  ErrString += fmt::format(
506  "\t - The phase became unstable (Cp < 0) T_unstable_last = {}\n",
507  Tunstable);
508  }
509  if (doUV) {
510  throw CanteraError("ThermoPhase::setState_HPorUV (UV)", ErrString);
511  } else {
512  throw CanteraError("ThermoPhase::setState_HPorUV (HP)", ErrString);
513  }
514 }
515 
516 void ThermoPhase::setState_SP(double Starget, double p, double rtol)
517 {
518  setState_SPorSV(Starget, p, rtol, false);
519 }
520 
521 void ThermoPhase::setState_SV(double Starget, double v, double rtol)
522 {
523  assertCompressible("setState_SV");
524  setState_SPorSV(Starget, v, rtol, true);
525 }
526 
527 void ThermoPhase::setState_SPorSV(double Starget, double p,
528  double rtol, bool doSV)
529 {
530  doublereal v = 0.0;
531  doublereal dt;
532  if (doSV) {
533  v = p;
534  if (v < 1.0E-300) {
535  throw CanteraError("ThermoPhase::setState_SPorSV (SV)",
536  "Input specific volume is too small or negative. v = {}", v);
537  }
538  setDensity(1.0/v);
539  } else {
540  if (p < 1.0E-300) {
541  throw CanteraError("ThermoPhase::setState_SPorSV (SP)",
542  "Input pressure is too small or negative. p = {}", p);
543  }
544  setPressure(p);
545  }
546  double Tmax = maxTemp() + 0.1;
547  double Tmin = minTemp() - 0.1;
548 
549  // Make sure we are within the temperature bounds at the start
550  // of the iteration
551  double Tnew = temperature();
552  double Tinit = Tnew;
553  if (Tnew > Tmax) {
554  Tnew = Tmax - 1.0;
555  } else if (Tnew < Tmin) {
556  Tnew = Tmin + 1.0;
557  }
558  if (Tnew != Tinit) {
559  setState_conditional_TP(Tnew, p, !doSV);
560  }
561 
562  double Snew = entropy_mass();
563  double Cpnew = (doSV) ? cv_mass() : cp_mass();
564  double Stop = Snew;
565  double Ttop = Tnew;
566  double Sbot = Snew;
567  double Tbot = Tnew;
568 
569  bool ignoreBounds = false;
570  // Unstable phases are those for which Cp < 0.0. These are possible for
571  // cases where we have passed the spinodal curve.
572  bool unstablePhase = false;
573  double Tunstable = -1.0;
574  bool unstablePhaseNew = false;
575 
576  // Newton iteration
577  for (int n = 0; n < 500; n++) {
578  double Told = Tnew;
579  double Sold = Snew;
580  double cpd = Cpnew;
581  if (cpd < 0.0) {
582  unstablePhase = true;
583  Tunstable = Tnew;
584  }
585  // limit step size to 100 K
586  dt = clip((Starget - Sold)*Told/cpd, -100.0, 100.0);
587  Tnew = Told + dt;
588 
589  // Limit the step size so that we are convergent
590  if ((dt > 0.0 && unstablePhase) || (dt <= 0.0 && !unstablePhase)) {
591  if (Sbot < Starget && Tnew < Tbot) {
592  dt = 0.75 * (Tbot - Told);
593  Tnew = Told + dt;
594  }
595  } else if (Stop > Starget && Tnew > Ttop) {
596  dt = 0.75 * (Ttop - Told);
597  Tnew = Told + dt;
598  }
599 
600  // Check Max and Min values
601  if (Tnew > Tmax && !ignoreBounds) {
602  setState_conditional_TP(Tmax, p, !doSV);
603  double Smax = entropy_mass();
604  if (Smax >= Starget) {
605  if (Stop < Starget) {
606  Ttop = Tmax;
607  Stop = Smax;
608  }
609  } else {
610  Tnew = Tmax + 1.0;
611  ignoreBounds = true;
612  }
613  } else if (Tnew < Tmin && !ignoreBounds) {
614  setState_conditional_TP(Tmin, p, !doSV);
615  double Smin = entropy_mass();
616  if (Smin <= Starget) {
617  if (Sbot > Starget) {
618  Tbot = Tmin;
619  Sbot = Smin;
620  }
621  } else {
622  Tnew = Tmin - 1.0;
623  ignoreBounds = true;
624  }
625  }
626 
627  // Try to keep phase within its region of stability
628  // -> Could do a lot better if I calculate the
629  // spinodal value of H.
630  for (int its = 0; its < 10; its++) {
631  Tnew = Told + dt;
632  setState_conditional_TP(Tnew, p, !doSV);
633  Cpnew = (doSV) ? cv_mass() : cp_mass();
634  Snew = entropy_mass();
635  if (Cpnew < 0.0) {
636  unstablePhaseNew = true;
637  Tunstable = Tnew;
638  } else {
639  unstablePhaseNew = false;
640  break;
641  }
642  if (unstablePhase == false && unstablePhaseNew == true) {
643  dt *= 0.25;
644  }
645  }
646 
647  if (Snew == Starget) {
648  return;
649  } else if (Snew > Starget && (Stop < Starget || Snew < Stop)) {
650  Stop = Snew;
651  Ttop = Tnew;
652  } else if (Snew < Starget && (Sbot > Starget || Snew > Sbot)) {
653  Sbot = Snew;
654  Tbot = Tnew;
655  }
656  // Convergence in S
657  double Serr = Starget - Snew;
658  double acpd = std::max(fabs(cpd), 1.0E-5);
659  double denom = std::max(fabs(Starget), acpd * Tnew);
660  double SConvErr = fabs((Serr * Tnew)/denom);
661  if (SConvErr < rtol || fabs(dt/Tnew) < rtol) {
662  return;
663  }
664  }
665  // We are here when there hasn't been convergence
666 
667  // Formulate a detailed error message, since questions seem to arise often
668  // about the lack of convergence.
669  string ErrString = "No convergence in 500 iterations\n";
670  if (doSV) {
671  ErrString += fmt::format(
672  "\tTarget Entropy = {}\n"
673  "\tCurrent Specific Volume = {}\n"
674  "\tStarting Temperature = {}\n"
675  "\tCurrent Temperature = {}\n"
676  "\tCurrent Entropy = {}\n"
677  "\tCurrent Delta T = {}\n",
678  Starget, v, Tinit, Tnew, Snew, dt);
679  } else {
680  ErrString += fmt::format(
681  "\tTarget Entropy = {}\n"
682  "\tCurrent Pressure = {}\n"
683  "\tStarting Temperature = {}\n"
684  "\tCurrent Temperature = {}\n"
685  "\tCurrent Entropy = {}\n"
686  "\tCurrent Delta T = {}\n",
687  Starget, p, Tinit, Tnew, Snew, dt);
688  }
689  if (unstablePhase) {
690  ErrString += fmt::format("\t - The phase became unstable (Cp < 0) T_unstable_last = {}\n",
691  Tunstable);
692  }
693  if (doSV) {
694  throw CanteraError("ThermoPhase::setState_SPorSV (SV)", ErrString);
695  } else {
696  throw CanteraError("ThermoPhase::setState_SPorSV (SP)", ErrString);
697  }
698 }
699 
700 double ThermoPhase::o2Required(const double* y) const
701 {
702  // indices of fuel elements
703  size_t iC = elementIndex("C");
704  size_t iS = elementIndex("S");
705  size_t iH = elementIndex("H");
706 
707  double o2req = 0.0;
708  double sum = 0.0;
709  for (size_t k = 0; k != m_kk; ++k) {
710  sum += y[k];
711  double x = y[k] / molecularWeights()[k];
712  if (iC != npos) {
713  o2req += x * nAtoms(k, iC);
714  }
715  if (iS != npos) {
716  o2req += x * nAtoms(k, iS);
717  }
718  if (iH != npos) {
719  o2req += x * 0.25 * nAtoms(k, iH);
720  }
721  }
722  if (sum == 0.0) {
723  throw CanteraError("ThermoPhase::o2Required",
724  "No composition specified");
725  }
726  return o2req/sum;
727 }
728 
729 double ThermoPhase::o2Present(const double* y) const
730 {
731  size_t iO = elementIndex("O");
732  double o2pres = 0.0;
733  double sum = 0.0;
734  for (size_t k = 0; k != m_kk; ++k) {
735  sum += y[k];
736  o2pres += y[k] / molecularWeights()[k] * nAtoms(k, iO);
737  }
738  if (sum == 0.0) {
739  throw CanteraError("ThermoPhase::o2Present",
740  "No composition specified");
741  }
742  return 0.5 * o2pres / sum;
743 }
744 
746  const compositionMap& oxComp,
747  ThermoBasis basis) const
748 {
749  vector_fp fuel(getCompositionFromMap(fuelComp));
750  vector_fp ox(getCompositionFromMap(oxComp));
751  return stoichAirFuelRatio(fuel.data(), ox.data(), basis);
752 }
753 
754 double ThermoPhase::stoichAirFuelRatio(const std::string& fuelComp,
755  const std::string& oxComp,
756  ThermoBasis basis) const
757 {
758  return stoichAirFuelRatio(
759  parseCompString(fuelComp.find(":") != std::string::npos ? fuelComp : fuelComp+":1.0"),
760  parseCompString(oxComp.find(":") != std::string::npos ? oxComp : oxComp+":1.0"),
761  basis);
762 }
763 
764 double ThermoPhase::stoichAirFuelRatio(const double* fuelComp,
765  const double* oxComp,
766  ThermoBasis basis) const
767 {
768  vector_fp fuel, ox;
769  if (basis == ThermoBasis::molar) { // convert input compositions to mass fractions
770  fuel.resize(m_kk);
771  ox.resize(m_kk);
772  moleFractionsToMassFractions(fuelComp, fuel.data());
773  moleFractionsToMassFractions(oxComp, ox.data());
774  fuelComp = fuel.data();
775  oxComp = ox.data();
776  }
777 
778  double o2_required_fuel = o2Required(fuelComp) - o2Present(fuelComp);
779  double o2_required_ox = o2Required(oxComp) - o2Present(oxComp);
780 
781  if (o2_required_fuel < 0.0 || o2_required_ox > 0.0) {
782  throw CanteraError("ThermoPhase::stoichAirFuelRatio",
783  "Fuel composition contains too much oxygen or "
784  "oxidizer contains not enough oxygen. "
785  "Fuel and oxidizer composition mixed up?");
786  }
787 
788  if (o2_required_ox == 0.0) {
789  return std::numeric_limits<double>::infinity();
790  }
791 
792  return o2_required_fuel / (-o2_required_ox);
793 }
794 
795 void ThermoPhase::setEquivalenceRatio(double phi, const double* fuelComp,
796  const double* oxComp, ThermoBasis basis)
797 {
798  if (phi < 0.0) {
799  throw CanteraError("ThermoPhase::setEquivalenceRatio",
800  "Equivalence ratio phi must be >= 0");
801  }
802 
803  double p = pressure();
804 
805  vector_fp fuel, ox;
806  if (basis == ThermoBasis::molar) { // convert input compositions to mass fractions
807  fuel.resize(m_kk);
808  ox.resize(m_kk);
809  moleFractionsToMassFractions(fuelComp, fuel.data());
810  moleFractionsToMassFractions(oxComp, ox.data());
811  fuelComp = fuel.data();
812  oxComp = ox.data();
813  }
814 
815  double AFR_st = stoichAirFuelRatio(fuelComp, oxComp, ThermoBasis::mass);
816 
817  double sum_f = std::accumulate(fuelComp, fuelComp+m_kk, 0.0);
818  double sum_o = std::accumulate(oxComp, oxComp+m_kk, 0.0);
819 
820  vector_fp y(m_kk);
821  for (size_t k = 0; k != m_kk; ++k) {
822  y[k] = phi * fuelComp[k]/sum_f + AFR_st * oxComp[k]/sum_o;
823  }
824 
825  setMassFractions(y.data());
826  setPressure(p);
827 }
828 
829 void ThermoPhase::setEquivalenceRatio(double phi, const std::string& fuelComp,
830  const std::string& oxComp, ThermoBasis basis)
831 {
833  parseCompString(fuelComp.find(":") != std::string::npos ? fuelComp : fuelComp+":1.0"),
834  parseCompString(oxComp.find(":") != std::string::npos ? oxComp : oxComp+":1.0"),
835  basis);
836 }
837 
838 void ThermoPhase::setEquivalenceRatio(double phi, const compositionMap& fuelComp,
839  const compositionMap& oxComp, ThermoBasis basis)
840 {
841  vector_fp fuel = getCompositionFromMap(fuelComp);
842  vector_fp ox = getCompositionFromMap(oxComp);
843  setEquivalenceRatio(phi, fuel.data(), ox.data(), basis);
844 }
845 
847 {
848  double o2_required = o2Required(massFractions());
849  double o2_present = o2Present(massFractions());
850 
851  if (o2_present == 0.0) { // pure fuel
852  return std::numeric_limits<double>::infinity();
853  }
854 
855  return o2_required / o2_present;
856 }
857 
859  const compositionMap& oxComp,
860  ThermoBasis basis) const
861 {
862  vector_fp fuel(getCompositionFromMap(fuelComp));
863  vector_fp ox(getCompositionFromMap(oxComp));
864  return equivalenceRatio(fuel.data(), ox.data(), basis);
865 }
866 
867 double ThermoPhase::equivalenceRatio(const std::string& fuelComp,
868  const std::string& oxComp,
869  ThermoBasis basis) const
870 {
871  return equivalenceRatio(
872  parseCompString(fuelComp.find(":") != std::string::npos ? fuelComp : fuelComp+":1.0"),
873  parseCompString(oxComp.find(":") != std::string::npos ? oxComp : oxComp+":1.0"),
874  basis);
875 }
876 
877 double ThermoPhase::equivalenceRatio(const double* fuelComp,
878  const double* oxComp,
879  ThermoBasis basis) const
880 {
881  double Z = mixtureFraction(fuelComp, oxComp, basis);
882 
883  if (Z == 0.0) {
884  return 0.0; // pure oxidizer
885  }
886 
887  if (Z == 1.0) {
888  return std::numeric_limits<double>::infinity(); // pure fuel
889  }
890 
891  vector_fp fuel, ox;
892  if (basis == ThermoBasis::molar) { // convert input compositions to mass fractions
893  fuel.resize(m_kk);
894  ox.resize(m_kk);
895  moleFractionsToMassFractions(fuelComp, fuel.data());
896  moleFractionsToMassFractions(oxComp, ox.data());
897  fuelComp = fuel.data();
898  oxComp = ox.data();
899  }
900 
901  double AFR_st = stoichAirFuelRatio(fuelComp, oxComp, ThermoBasis::mass);
902 
903  return std::max(Z / (1.0 - Z) * AFR_st, 0.0);
904 }
905 
906 void ThermoPhase::setMixtureFraction(double mixFrac, const compositionMap& fuelComp,
907  const compositionMap& oxComp, ThermoBasis basis)
908 {
909  vector_fp fuel(getCompositionFromMap(fuelComp));
910  vector_fp ox(getCompositionFromMap(oxComp));
911  setMixtureFraction(mixFrac, fuel.data(), ox.data(), basis);
912 }
913 
914 void ThermoPhase::setMixtureFraction(double mixFrac, const std::string& fuelComp,
915  const std::string& oxComp, ThermoBasis basis)
916 {
917  setMixtureFraction(mixFrac,
918  parseCompString(fuelComp.find(":") != std::string::npos ? fuelComp : fuelComp+":1.0"),
919  parseCompString(oxComp.find(":") != std::string::npos ? oxComp : oxComp+":1.0"),
920  basis);
921 }
922 
923 void ThermoPhase::setMixtureFraction(double mixFrac, const double* fuelComp,
924  const double* oxComp, ThermoBasis basis)
925 {
926  if (mixFrac < 0.0 || mixFrac > 1.0) {
927  throw CanteraError("ThermoPhase::setMixtureFraction",
928  "Mixture fraction must be between 0 and 1");
929  }
930 
931  vector_fp fuel, ox;
932  if (basis == ThermoBasis::molar) { // convert input compositions to mass fractions
933  fuel.resize(m_kk);
934  ox.resize(m_kk);
935  moleFractionsToMassFractions(fuelComp, fuel.data());
936  moleFractionsToMassFractions(oxComp, ox.data());
937  fuelComp = fuel.data();
938  oxComp = ox.data();
939  }
940 
941  double sum_yf = std::accumulate(fuelComp, fuelComp+m_kk, 0.0);
942  double sum_yo = std::accumulate(oxComp, oxComp+m_kk, 0.0);
943 
944  if (sum_yf == 0.0 || sum_yo == 0.0) {
945  throw CanteraError("ThermoPhase::setMixtureFraction",
946  "No fuel and/or oxidizer composition specified");
947  }
948 
949  double p = pressure();
950 
951  vector_fp y(m_kk);
952 
953  for (size_t k = 0; k != m_kk; ++k) {
954  y[k] = mixFrac * fuelComp[k]/sum_yf + (1.0-mixFrac) * oxComp[k]/sum_yo;
955  }
956 
957  setMassFractions_NoNorm(y.data());
958  setPressure(p);
959 }
960 
962  const compositionMap& oxComp,
963  ThermoBasis basis,
964  const std::string& element) const
965 {
966  vector_fp fuel(getCompositionFromMap(fuelComp));
967  vector_fp ox(getCompositionFromMap(oxComp));
968  return mixtureFraction(fuel.data(), ox.data(), basis, element);
969 }
970 
971 double ThermoPhase::mixtureFraction(const std::string& fuelComp,
972  const std::string& oxComp,
973  ThermoBasis basis,
974  const std::string& element) const
975 {
976  return mixtureFraction(
977  parseCompString(fuelComp.find(":") != std::string::npos ? fuelComp : fuelComp+":1.0"),
978  parseCompString(oxComp.find(":") != std::string::npos ? oxComp : oxComp+":1.0"),
979  basis, element);
980 }
981 
982 double ThermoPhase::mixtureFraction(const double* fuelComp,
983  const double* oxComp,
984  ThermoBasis basis,
985  const std::string& element) const
986 {
987  vector_fp fuel, ox;
988  if (basis == ThermoBasis::molar) { // convert input compositions to mass fractions
989  fuel.resize(m_kk);
990  ox.resize(m_kk);
991  moleFractionsToMassFractions(fuelComp, fuel.data());
992  moleFractionsToMassFractions(oxComp, ox.data());
993  fuelComp = fuel.data();
994  oxComp = ox.data();
995  }
996 
997  if (element == "Bilger") // compute the mixture fraction based on the Bilger mixture fraction
998  {
999  double o2_required_fuel = o2Required(fuelComp) - o2Present(fuelComp);
1000  double o2_required_ox = o2Required(oxComp) - o2Present(oxComp);
1001  double o2_required_mix = o2Required(massFractions()) - o2Present(massFractions());
1002 
1003  if (o2_required_fuel < 0.0 || o2_required_ox > 0.0) {
1004  throw CanteraError("ThermoPhase::mixtureFraction",
1005  "Fuel composition contains too much oxygen or "
1006  "oxidizer contains not enough oxygen. "
1007  "Fuel and oxidizer composition mixed up?");
1008  }
1009 
1010  double denominator = o2_required_fuel - o2_required_ox;
1011 
1012  if (denominator == 0.0) {
1013  throw CanteraError("ThermoPhase::mixtureFraction",
1014  "Fuel and oxidizer have the same composition");
1015  }
1016 
1017  double Z = (o2_required_mix - o2_required_ox) / denominator;
1018 
1019  return std::min(std::max(Z, 0.0), 1.0);
1020  } else {
1021  // compute the mixture fraction from a single element
1022  double sum_yf = std::accumulate(fuelComp, fuelComp+m_kk, 0.0);
1023  double sum_yo = std::accumulate(oxComp, oxComp+m_kk, 0.0);
1024 
1025  if (sum_yf == 0.0 || sum_yo == 0.0) {
1026  throw CanteraError("ThermoPhase::mixtureFraction",
1027  "No fuel and/or oxidizer composition specified");
1028  }
1029 
1030  auto elementalFraction = [this](size_t m, const double* y) {
1031  double Z_m = 0.0;
1032  for (size_t k = 0; k != m_kk; ++k) {
1033  Z_m += y[k] / molecularWeight(k) * nAtoms(k, m);
1034  }
1035  return Z_m;
1036  };
1037 
1038  size_t m = elementIndex(element);
1039  double Z_m_fuel = elementalFraction(m, fuelComp)/sum_yf;
1040  double Z_m_ox = elementalFraction(m, oxComp)/sum_yo;
1041  double Z_m_mix = elementalFraction(m, massFractions());
1042 
1043  if (Z_m_fuel == Z_m_ox) {
1044  throw CanteraError("ThermoPhase::mixtureFraction",
1045  "Fuel and oxidizer have the same composition for element {}",
1046  element);
1047  }
1048  double Z = (Z_m_mix - Z_m_ox) / (Z_m_fuel - Z_m_ox);
1049  return std::min(std::max(Z, 0.0), 1.0);
1050  }
1051 }
1052 
1054 {
1055  return m_spthermo;
1056 }
1057 
1059 {
1060  return m_spthermo;
1061 }
1062 
1063 
1064 void ThermoPhase::initThermoFile(const std::string& inputFile,
1065  const std::string& id)
1066 {
1067  size_t dot = inputFile.find_last_of(".");
1068  string extension;
1069  if (dot != npos) {
1070  extension = inputFile.substr(dot+1);
1071  }
1072 
1073  if (extension == "yml" || extension == "yaml") {
1074  AnyMap root = AnyMap::fromYamlFile(inputFile);
1075  auto& phase = root["phases"].getMapWhere("name", id);
1076  setupPhase(*this, phase, root);
1077  } else {
1078  XML_Node* fxml = get_XML_File(inputFile);
1079  XML_Node* fxml_phase = findXMLPhase(fxml, id);
1080  if (!fxml_phase) {
1081  throw CanteraError("ThermoPhase::initThermoFile",
1082  "ERROR: Can not find phase named {} in file"
1083  " named {}", id, inputFile);
1084  }
1085  importPhase(*fxml_phase, this);
1086  }
1087 }
1088 
1089 void ThermoPhase::initThermoXML(XML_Node& phaseNode, const std::string& id)
1090 {
1091  if (phaseNode.hasChild("state")) {
1092  setStateFromXML(phaseNode.child("state"));
1093  }
1094 }
1095 
1097 {
1098  // Check to see that all of the species thermo objects have been initialized
1099  if (!m_spthermo.ready(m_kk)) {
1100  throw CanteraError("ThermoPhase::initThermo()",
1101  "Missing species thermo data");
1102  }
1103 }
1104 
1105 void ThermoPhase::setState_TPQ(double T, double P, double Q)
1106 {
1107  if (T > critTemperature()) {
1108  if (P > critPressure() || Q == 1) {
1109  setState_TP(T, P);
1110  return;
1111  } else {
1112  throw CanteraError("ThermoPhase::setState_TPQ",
1113  "Temperature ({}), pressure ({}) and vapor fraction ({}) "
1114  "are inconsistent, above the critical temperature.",
1115  T, P, Q);
1116  }
1117  }
1118 
1119  double Psat = satPressure(T);
1120  if (std::abs(Psat / P - 1) < 1e-6) {
1121  setState_Tsat(T, Q);
1122  } else if ((Q == 0 && P >= Psat) || (Q == 1 && P <= Psat)) {
1123  setState_TP(T, P);
1124  } else {
1125  throw CanteraError("ThermoPhase::setState_TPQ",
1126  "Temperature ({}), pressure ({}) and vapor fraction ({}) "
1127  "are inconsistent.\nPsat at this T: {}\n"
1128  "Consider specifying the state using two fully independent "
1129  "properties (e.g. temperature and density)",
1130  T, P, Q, Psat);
1131  }
1132 }
1133 
1134 bool ThermoPhase::addSpecies(shared_ptr<Species> spec)
1135 {
1136  if (!spec->thermo) {
1137  throw CanteraError("ThermoPhase::addSpecies",
1138  "Species {} has no thermo data", spec->name);
1139  }
1140  bool added = Phase::addSpecies(spec);
1141  if (added) {
1142  spec->thermo->validate(spec->name);
1143  m_spthermo.install_STIT(m_kk-1, spec->thermo);
1144  }
1145  return added;
1146 }
1147 
1148 void ThermoPhase::modifySpecies(size_t k, shared_ptr<Species> spec)
1149 {
1150  if (!spec->thermo) {
1151  throw CanteraError("ThermoPhase::modifySpecies",
1152  "Species {} has no thermo data", spec->name);
1153  }
1154  Phase::modifySpecies(k, spec);
1155  if (speciesName(k) != spec->name) {
1156  throw CanteraError("ThermoPhase::modifySpecies",
1157  "New species '{}' does not match existing species '{}' at index {}",
1158  spec->name, speciesName(k), k);
1159  }
1160  spec->thermo->validate(spec->name);
1161  m_spthermo.modifySpecies(k, spec->thermo);
1162 }
1163 
1164 void ThermoPhase::saveSpeciesData(const size_t k, const XML_Node* const data)
1165 {
1166  if (m_speciesData.size() < (k + 1)) {
1167  m_speciesData.resize(k+1, 0);
1168  }
1169  m_speciesData[k] = new XML_Node(*data);
1170 }
1171 
1172 const std::vector<const XML_Node*> & ThermoPhase::speciesData() const
1173 {
1174  if (m_speciesData.size() != m_kk) {
1175  throw CanteraError("ThermoPhase::speciesData",
1176  "m_speciesData is the wrong size");
1177  }
1178  return m_speciesData;
1179 }
1180 
1181 void ThermoPhase::setParameters(const AnyMap& phaseNode, const AnyMap& rootNode)
1182 {
1183  m_input = phaseNode;
1184 }
1185 
1187 {
1188  return m_input;
1189 }
1190 
1192 {
1193  return m_input;
1194 }
1195 
1197 {
1198  string comp = getChildValue(state,"moleFractions");
1199  if (comp != "") {
1200  setMoleFractionsByName(comp);
1201  } else {
1202  comp = getChildValue(state,"massFractions");
1203  if (comp != "") {
1204  setMassFractionsByName(comp);
1205  }
1206  }
1207  if (state.hasChild("temperature")) {
1208  double t = getFloat(state, "temperature", "temperature");
1209  setTemperature(t);
1210  }
1211  if (state.hasChild("pressure")) {
1212  double p = getFloat(state, "pressure", "pressure");
1213  setPressure(p);
1214  }
1215  if (state.hasChild("density")) {
1216  double rho = getFloat(state, "density", "density");
1217  setDensity(rho);
1218  }
1219 }
1220 
1223  m_tlast += 0.1234;
1224 }
1225 
1226 void ThermoPhase::equilibrate(const std::string& XY, const std::string& solver,
1227  double rtol, int max_steps, int max_iter,
1228  int estimate_equil, int log_level)
1229 {
1230  if (solver == "auto" || solver == "element_potential") {
1231  vector_fp initial_state;
1232  saveState(initial_state);
1233  debuglog("Trying ChemEquil solver\n", log_level);
1234  try {
1235  ChemEquil E;
1236  E.options.maxIterations = max_steps;
1237  E.options.relTolerance = rtol;
1238  int ret = E.equilibrate(*this, XY.c_str(), log_level-1);
1239  if (ret < 0) {
1240  throw CanteraError("ThermoPhase::equilibrate",
1241  "ChemEquil solver failed. Return code: {}", ret);
1242  }
1243  debuglog("ChemEquil solver succeeded\n", log_level);
1244  return;
1245  } catch (std::exception& err) {
1246  debuglog("ChemEquil solver failed.\n", log_level);
1247  debuglog(err.what(), log_level);
1248  restoreState(initial_state);
1249  if (solver == "auto") {
1250  } else {
1251  throw;
1252  }
1253  }
1254  }
1255 
1256  if (solver == "auto" || solver == "vcs" || solver == "gibbs") {
1257  MultiPhase M;
1258  M.addPhase(this, 1.0);
1259  M.init();
1260  M.equilibrate(XY, solver, rtol, max_steps, max_iter,
1261  estimate_equil, log_level);
1262  return;
1263  }
1264 
1265  if (solver != "auto") {
1266  throw CanteraError("ThermoPhase::equilibrate",
1267  "Invalid solver specified: '{}'", solver);
1268  }
1269 }
1270 
1271 void ThermoPhase::getdlnActCoeffdlnN(const size_t ld, doublereal* const dlnActCoeffdlnN)
1272 {
1273  for (size_t m = 0; m < m_kk; m++) {
1274  for (size_t k = 0; k < m_kk; k++) {
1275  dlnActCoeffdlnN[ld * k + m] = 0.0;
1276  }
1277  }
1278  return;
1279 }
1280 
1281 void ThermoPhase::getdlnActCoeffdlnN_numderiv(const size_t ld, doublereal* const dlnActCoeffdlnN)
1282 {
1283  double deltaMoles_j = 0.0;
1284  double pres = pressure();
1285 
1286  // Evaluate the current base activity coefficients if necessary
1287  vector_fp ActCoeff_Base(m_kk);
1288  getActivityCoefficients(ActCoeff_Base.data());
1289  vector_fp Xmol_Base(m_kk);
1290  getMoleFractions(Xmol_Base.data());
1291 
1292  // Make copies of ActCoeff and Xmol_ for use in taking differences
1293  vector_fp ActCoeff(m_kk);
1294  vector_fp Xmol(m_kk);
1295  double v_totalMoles = 1.0;
1296  double TMoles_base = v_totalMoles;
1297 
1298  // Loop over the columns species to be deltad
1299  for (size_t j = 0; j < m_kk; j++) {
1300  // Calculate a value for the delta moles of species j
1301  // -> Note Xmol_[] and Tmoles are always positive or zero quantities.
1302  // -> experience has shown that you always need to make the deltas
1303  // greater than needed to change the other mole fractions in order
1304  // to capture some effects.
1305  double moles_j_base = v_totalMoles * Xmol_Base[j];
1306  deltaMoles_j = 1.0E-7 * moles_j_base + v_totalMoles * 1.0E-13 + 1.0E-150;
1307 
1308  // Now, update the total moles in the phase and all of the mole
1309  // fractions based on this.
1310  v_totalMoles = TMoles_base + deltaMoles_j;
1311  for (size_t k = 0; k < m_kk; k++) {
1312  Xmol[k] = Xmol_Base[k] * TMoles_base / v_totalMoles;
1313  }
1314  Xmol[j] = (moles_j_base + deltaMoles_j) / v_totalMoles;
1315 
1316  // Go get new values for the activity coefficients.
1317  // -> Note this calls setState_PX();
1318  setState_PX(pres, Xmol.data());
1319  getActivityCoefficients(ActCoeff.data());
1320 
1321  // Calculate the column of the matrix
1322  double* const lnActCoeffCol = dlnActCoeffdlnN + ld * j;
1323  for (size_t k = 0; k < m_kk; k++) {
1324  lnActCoeffCol[k] = (2*moles_j_base + deltaMoles_j) *(ActCoeff[k] - ActCoeff_Base[k]) /
1325  ((ActCoeff[k] + ActCoeff_Base[k]) * deltaMoles_j);
1326  }
1327  // Revert to the base case Xmol_, v_totalMoles
1328  v_totalMoles = TMoles_base;
1329  Xmol = Xmol_Base;
1330  }
1331 
1332  setState_PX(pres, Xmol_Base.data());
1333 }
1334 
1335 std::string ThermoPhase::report(bool show_thermo, doublereal threshold) const
1336 {
1337  fmt::memory_buffer b;
1338  // This is the width of the first column of names in the report.
1339  int name_width = 18;
1340 
1341  string blank_leader = fmt::format("{:{}}", "", name_width);
1342 
1343  string one_property = "{:>{}} {:<.5g} {}\n";
1344 
1345  string two_prop_header = "{} {:^15} {:^15}\n";
1346  string kg_kmol_header = fmt::format(
1347  two_prop_header, blank_leader, "1 kg", "1 kmol"
1348  );
1349  string Y_X_header = fmt::format(
1350  two_prop_header, blank_leader, "mass frac. Y", "mole frac. X"
1351  );
1352  string two_prop_sep = fmt::format(
1353  "{} {:-^15} {:-^15}\n", blank_leader, "", ""
1354  );
1355  string two_property = "{:>{}} {:15.5g} {:15.5g} {}\n";
1356 
1357  string three_prop_header = fmt::format(
1358  "{} {:^15} {:^15} {:^15}\n", blank_leader, "mass frac. Y",
1359  "mole frac. X", "chem. pot. / RT"
1360  );
1361  string three_prop_sep = fmt::format(
1362  "{} {:-^15} {:-^15} {:-^15}\n", blank_leader, "", "", ""
1363  );
1364  string three_property = "{:>{}} {:15.5g} {:15.5g} {:15.5g}\n";
1365 
1366  try {
1367  if (name() != "") {
1368  format_to(b, "\n {}:\n", name());
1369  }
1370  format_to(b, "\n");
1371  format_to(b, one_property, "temperature", name_width, temperature(), "K");
1372  format_to(b, one_property, "pressure", name_width, pressure(), "Pa");
1373  format_to(b, one_property, "density", name_width, density(), "kg/m^3");
1374  format_to(b, one_property, "mean mol. weight", name_width, meanMolecularWeight(), "kg/kmol");
1375 
1376  double phi = electricPotential();
1377  if (phi != 0.0) {
1378  format_to(b, one_property, "potential", name_width, phi, "V");
1379  }
1380 
1381  format_to(b, "{:>{}} {}\n", "phase of matter", name_width, phaseOfMatter());
1382 
1383  if (show_thermo) {
1384  format_to(b, "\n");
1385  format_to(b, kg_kmol_header);
1386  format_to(b, two_prop_sep);
1387  format_to(b, two_property, "enthalpy", name_width, enthalpy_mass(), enthalpy_mole(), "J");
1388  format_to(b, two_property, "internal energy", name_width, intEnergy_mass(), intEnergy_mole(), "J");
1389  format_to(b, two_property, "entropy", name_width, entropy_mass(), entropy_mole(), "J/K");
1390  format_to(b, two_property, "Gibbs function", name_width, gibbs_mass(), gibbs_mole(), "J");
1391  format_to(b, two_property, "heat capacity c_p", name_width, cp_mass(), cp_mole(), "J/K");
1392  try {
1393  format_to(b, two_property, "heat capacity c_v", name_width, cv_mass(), cv_mole(), "J/K");
1394  } catch (NotImplementedError&) {
1395  format_to(b, "{:>{}} <not implemented> \n", "heat capacity c_v", name_width);
1396  }
1397  }
1398 
1399  vector_fp x(m_kk);
1400  vector_fp y(m_kk);
1401  vector_fp mu(m_kk);
1402  getMoleFractions(&x[0]);
1403  getMassFractions(&y[0]);
1404  getChemPotentials(&mu[0]);
1405  int nMinor = 0;
1406  double xMinor = 0.0;
1407  double yMinor = 0.0;
1408  format_to(b, "\n");
1409  if (show_thermo) {
1410  format_to(b, three_prop_header);
1411  format_to(b, three_prop_sep);
1412  for (size_t k = 0; k < m_kk; k++) {
1413  if (abs(x[k]) >= threshold) {
1414  if (abs(x[k]) > SmallNumber) {
1415  format_to(b, three_property, speciesName(k), name_width, y[k], x[k], mu[k]/RT());
1416  } else {
1417  format_to(b, two_property, speciesName(k), name_width, y[k], x[k], "");
1418  }
1419  } else {
1420  nMinor++;
1421  xMinor += x[k];
1422  yMinor += y[k];
1423  }
1424  }
1425  } else {
1426  format_to(b, Y_X_header);
1427  format_to(b, two_prop_sep);
1428  for (size_t k = 0; k < m_kk; k++) {
1429  if (abs(x[k]) >= threshold) {
1430  format_to(b, two_property, speciesName(k), name_width, y[k], x[k], "");
1431  } else {
1432  nMinor++;
1433  xMinor += x[k];
1434  yMinor += y[k];
1435  }
1436  }
1437  }
1438  if (nMinor) {
1439  string minor = fmt::format("[{:+5d} minor]", nMinor);
1440  format_to(b, two_property, minor, name_width, yMinor, xMinor, "");
1441  }
1442  } catch (CanteraError& err) {
1443  return to_string(b) + err.what();
1444  }
1445  return to_string(b);
1446 }
1447 
1448 void ThermoPhase::reportCSV(std::ofstream& csvFile) const
1449 {
1450  int tabS = 15;
1451  int tabM = 30;
1452  csvFile.precision(8);
1453  vector_fp X(nSpecies());
1454  getMoleFractions(&X[0]);
1455  std::vector<std::string> pNames;
1456  std::vector<vector_fp> data;
1457  getCsvReportData(pNames, data);
1458 
1459  csvFile << setw(tabS) << "Species,";
1460  for (size_t i = 0; i < pNames.size(); i++) {
1461  csvFile << setw(tabM) << pNames[i] << ",";
1462  }
1463  csvFile << endl;
1464  for (size_t k = 0; k < nSpecies(); k++) {
1465  csvFile << setw(tabS) << speciesName(k) + ",";
1466  if (X[k] > SmallNumber) {
1467  for (size_t i = 0; i < pNames.size(); i++) {
1468  csvFile << setw(tabM) << data[i][k] << ",";
1469  }
1470  csvFile << endl;
1471  } else {
1472  for (size_t i = 0; i < pNames.size(); i++) {
1473  csvFile << setw(tabM) << 0 << ",";
1474  }
1475  csvFile << endl;
1476  }
1477  }
1478 }
1479 
1480 void ThermoPhase::getCsvReportData(std::vector<std::string>& names,
1481  std::vector<vector_fp>& data) const
1482 {
1483  names.clear();
1484  data.assign(10, vector_fp(nSpecies()));
1485 
1486  names.push_back("X");
1487  getMoleFractions(&data[0][0]);
1488 
1489  names.push_back("Y");
1490  getMassFractions(&data[1][0]);
1491 
1492  names.push_back("Chem. Pot (J/kmol)");
1493  getChemPotentials(&data[2][0]);
1494 
1495  names.push_back("Activity");
1496  getActivities(&data[3][0]);
1497 
1498  names.push_back("Act. Coeff.");
1499  getActivityCoefficients(&data[4][0]);
1500 
1501  names.push_back("Part. Mol Enthalpy (J/kmol)");
1502  getPartialMolarEnthalpies(&data[5][0]);
1503 
1504  names.push_back("Part. Mol. Entropy (J/K/kmol)");
1505  getPartialMolarEntropies(&data[6][0]);
1506 
1507  names.push_back("Part. Mol. Energy (J/kmol)");
1508  getPartialMolarIntEnergies(&data[7][0]);
1509 
1510  names.push_back("Part. Mol. Cp (J/K/kmol");
1511  getPartialMolarCp(&data[8][0]);
1512 
1513  names.push_back("Part. Mol. Cv (J/K/kmol)");
1514  getPartialMolarVolumes(&data[9][0]);
1515 }
1516 
1517 }
Cantera::ThermoPhase::setState_SH
virtual void setState_SH(double s, double h, double tol=1e-9)
Set the specific entropy (J/kg/K) and the specific enthalpy (J/kg)
Definition: ThermoPhase.h:1055
Cantera::ThermoPhase::initThermoXML
virtual void initThermoXML(XML_Node &phaseNode, const std::string &id)
Import and initialize a ThermoPhase object using an XML tree.
Definition: ThermoPhase.cpp:1089
Cantera::Phase::setMassFractionsByName
void setMassFractionsByName(const compositionMap &yMap)
Set the species mass fractions by name.
Definition: Phase.cpp:445
Cantera::ThermoPhase::enthalpy_mass
doublereal enthalpy_mass() const
Specific enthalpy. Units: J/kg.
Definition: ThermoPhase.h:742
Cantera::getChildValue
std::string getChildValue(const XML_Node &parent, const std::string &nameString)
This function reads a child node with the name, nameString, and returns its XML value as the return s...
Definition: ctml.cpp:131
Cantera::Phase::modifySpecies
virtual void modifySpecies(size_t k, shared_ptr< Species > spec)
Modify the thermodynamic data associated with a species.
Definition: Phase.cpp:929
Cantera::ThermoPhase::enthalpy_mole
virtual doublereal enthalpy_mole() const
Molar enthalpy. Units: J/kmol.
Definition: ThermoPhase.h:234
Cantera::ThermoPhase::setStateFromXML
virtual void setStateFromXML(const XML_Node &state)
Set the initial state of the phase to the conditions specified in the state XML element.
Definition: ThermoPhase.cpp:1196
Cantera::EquilOpt::relTolerance
doublereal relTolerance
Relative tolerance.
Definition: ChemEquil.h:34
Cantera::Phase::invalidateCache
virtual void invalidateCache()
Invalidate any cached values which are normally updated only when a change in state is detected.
Definition: Phase.cpp:1014
Cantera::ThermoPhase::intEnergy_mole
virtual doublereal intEnergy_mole() const
Molar internal energy. Units: J/kmol.
Definition: ThermoPhase.h:239
Cantera::ThermoPhase::cv_mass
doublereal cv_mass() const
Specific heat at constant volume. Units: J/kg/K.
Definition: ThermoPhase.h:767
Cantera::ThermoPhase::standardConcentration
virtual doublereal standardConcentration(size_t k=0) const
Return the standard concentration for the kth species.
Definition: ThermoPhase.h:419
Cantera::ThermoPhase::setState_PX
virtual void setState_PX(doublereal p, doublereal *x)
Set the pressure (Pa) and mole fractions.
Definition: ThermoPhase.cpp:185
Cantera::compositionMap
std::map< std::string, double > compositionMap
Map connecting a string name with a double.
Definition: ct_defs.h:172
Cantera::ThermoPhase::getElectrochemPotentials
void getElectrochemPotentials(doublereal *mu) const
Get the species electrochemical potentials.
Definition: ThermoPhase.cpp:91
Cantera::findXMLPhase
XML_Node * findXMLPhase(XML_Node *root, const std::string &phaseId)
Search an XML_Node tree for a named phase XML_Node.
Definition: xml.cpp:1038
Cantera::Phase::setPressure
virtual void setPressure(double p)
Set the internally stored pressure (Pa) at constant temperature and composition.
Definition: Phase.h:718
Cantera::ThermoPhase::setState_PY
virtual void setState_PY(doublereal p, doublereal *y)
Set the internally stored pressure (Pa) and mass fractions.
Definition: ThermoPhase.cpp:191
Cantera::get_XML_File
XML_Node * get_XML_File(const std::string &file, int debug)
Return a pointer to the XML tree for a Cantera input file.
Definition: global.cpp:110
Cantera::Phase::getMoleFractions
void getMoleFractions(double *const x) const
Get the species mole fraction vector.
Definition: Phase.cpp:572
Cantera::ThermoPhase::getActivities
virtual void getActivities(doublereal *a) const
Get the array of non-dimensional activities at the current solution temperature, pressure,...
Definition: ThermoPhase.cpp:75
Cantera::SmallNumber
const double SmallNumber
smallest number to compare to zero.
Definition: ct_defs.h:149
Cantera::AnyMap::convert
double convert(const std::string &key, const std::string &units) const
Convert the item stored by the given key to the units specified in units.
Definition: AnyMap.cpp:1055
Cantera::cAC_CONVENTION_MOLAR
const int cAC_CONVENTION_MOLAR
Standard state uses the molar convention.
Definition: ThermoPhase.h:26
Cantera::MultiSpeciesThermo::ready
bool ready(size_t nSpecies)
Check if data for all species (0 through nSpecies-1) has been installed.
Definition: MultiSpeciesThermo.cpp:208
Cantera::ChemEquil::options
EquilOpt options
Options controlling how the calculation is carried out.
Definition: ChemEquil.h:131
Cantera::CanteraError::what
const char * what() const
Get a description of the error.
Definition: ctexceptions.cpp:24
Cantera::ThermoPhase::intEnergy_mass
doublereal intEnergy_mass() const
Specific internal energy. Units: J/kg.
Definition: ThermoPhase.h:747
Cantera::Phase::assertCompressible
void assertCompressible(const std::string &setter) const
Ensure that phase is compressible.
Definition: Phase.h:902
Cantera::Phase::massFractions
const double * massFractions() const
Return a const pointer to the mass fraction array.
Definition: Phase.h:544
Cantera::MultiSpeciesThermo::resetHf298
virtual void resetHf298(const size_t k)
Restore the original heat of formation of one or more species.
Definition: MultiSpeciesThermo.cpp:200
Cantera::Phase::addSpecies
virtual bool addSpecies(shared_ptr< Species > spec)
Add a Species to this Phase.
Definition: Phase.cpp:833
Cantera::clip
T clip(const T &value, const T &lower, const T &upper)
Clip value such that lower <= value <= upper.
Definition: global.h:300
Cantera::NotImplementedError
An error indicating that an unimplemented function has been called.
Definition: ctexceptions.h:186
Cantera::Phase::meanMolecularWeight
doublereal meanMolecularWeight() const
The mean molecular weight. Units: (kg/kmol)
Definition: Phase.h:748
Cantera::ThermoPhase::getdlnActCoeffdlnN
virtual void getdlnActCoeffdlnN(const size_t ld, doublereal *const dlnActCoeffdlnN)
Get the array of derivatives of the log activity coefficients with respect to the log of the species ...
Definition: ThermoPhase.cpp:1271
Cantera::ThermoPhase::activityConvention
virtual int activityConvention() const
This method returns the convention used in specification of the activities, of which there are curren...
Definition: ThermoPhase.cpp:54
Cantera::Phase::setTemperature
virtual void setTemperature(const doublereal temp)
Set the internally stored temperature of the phase (K).
Definition: Phase.h:724
Cantera::XML_Node::hasChild
bool hasChild(const std::string &ch) const
Tests whether the current node has a child node with a particular name.
Definition: xml.cpp:528
Cantera::AnyMap::hasKey
bool hasKey(const std::string &key) const
Returns true if the map contains an item named key.
Definition: AnyMap.cpp:984
Cantera::ThermoPhase::getPartialMolarEnthalpies
virtual void getPartialMolarEnthalpies(doublereal *hbar) const
Returns an array of partial molar enthalpies for the species in the mixture.
Definition: ThermoPhase.h:515
Cantera::ThermoPhase::equilibrate
void equilibrate(const std::string &XY, const std::string &solver="auto", double rtol=1e-9, int max_steps=50000, int max_iter=100, int estimate_equil=0, int log_level=0)
Equilibrate a ThermoPhase object.
Definition: ThermoPhase.cpp:1226
Cantera::ThermoPhase::setState_TPY
virtual void setState_TPY(doublereal t, doublereal p, const doublereal *y)
Set the internally stored temperature (K), pressure (Pa), and mass fractions of the phase.
Definition: ThermoPhase.cpp:118
Cantera::ThermoPhase::getPartialMolarIntEnergies
virtual void getPartialMolarIntEnergies(doublereal *ubar) const
Return an array of partial molar internal energies for the species in the mixture.
Definition: ThermoPhase.h:535
Cantera::ThermoPhase::cp_mole
virtual doublereal cp_mole() const
Molar heat capacity at constant pressure. Units: J/kmol/K.
Definition: ThermoPhase.h:254
Cantera::cSS_CONVENTION_TEMPERATURE
const int cSS_CONVENTION_TEMPERATURE
Standard state uses the molar convention.
Definition: ThermoPhase.h:36
ChemEquil.h
Cantera::MultiPhase
A class for multiphase mixtures.
Definition: MultiPhase.h:57
Cantera::Phase::nDim
size_t nDim() const
Returns the number of spatial dimensions (1, 2, or 3)
Definition: Phase.h:651
Cantera::ThermoPhase::stoichAirFuelRatio
double stoichAirFuelRatio(const double *fuelComp, const double *oxComp, ThermoBasis basis=ThermoBasis::molar) const
Compute the stoichiometric air to fuel ratio (kg oxidizer / kg fuel) given fuel and oxidizer composit...
Definition: ThermoPhase.cpp:764
Cantera::ThermoPhase::setState_UV
virtual void setState_UV(double u, double v, double tol=1e-9)
Set the specific internal energy (J/kg) and specific volume (m^3/kg).
Definition: ThermoPhase.cpp:202
Cantera::MultiSpeciesThermo::modifySpecies
virtual void modifySpecies(size_t index, shared_ptr< SpeciesThermoInterpType > spec)
Modify the species thermodynamic property parameterization for a species.
Definition: MultiSpeciesThermo.cpp:49
Cantera::ThermoPhase::setState_TP
virtual void setState_TP(doublereal t, doublereal p)
Set the temperature (K) and pressure (Pa)
Definition: ThermoPhase.cpp:136
Cantera::ThermoPhase::getActivityCoefficients
virtual void getActivityCoefficients(doublereal *ac) const
Get the array of non-dimensional molar-based activity coefficients at the current solution temperatur...
Definition: ThermoPhase.h:448
Cantera::ThermoPhase::setState_SP
virtual void setState_SP(double s, double p, double tol=1e-9)
Set the specific entropy (J/kg/K) and pressure (Pa).
Definition: ThermoPhase.cpp:516
ThermoFactory.h
Cantera::vector_fp
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
Definition: ct_defs.h:180
Cantera::ThermoBasis
ThermoBasis
Differentiate between mole fractions and mass fractions for input mixture composition.
Definition: ThermoPhase.h:44
Cantera::ThermoPhase::equivalenceRatio
double equivalenceRatio() const
Compute the equivalence ratio for the current mixture from available oxygen and required oxygen.
Definition: ThermoPhase.cpp:846
Cantera::ThermoPhase::standardStateConvention
virtual int standardStateConvention() const
This method returns the convention used in specification of the standard state, of which there are cu...
Definition: ThermoPhase.cpp:59
Cantera::Phase::name
std::string name() const
Return the name of the phase.
Definition: Phase.cpp:84
Cantera::ThermoPhase::setState
virtual void setState(const AnyMap &state)
Set the state using an AnyMap containing any combination of properties supported by the thermodynamic...
Definition: ThermoPhase.cpp:208
Cantera::ThermoPhase::mixtureFraction
double mixtureFraction(const double *fuelComp, const double *oxComp, ThermoBasis basis=ThermoBasis::molar, const std::string &element="Bilger") const
Compute the mixture fraction = kg fuel / (kg oxidizer + kg fuel) for the current mixture given fuel a...
Definition: ThermoPhase.cpp:982
Cantera::ChemEquil
Class ChemEquil implements a chemical equilibrium solver for single-phase solutions.
Definition: ChemEquil.h:82
Cantera::ThermoPhase::getLnActivityCoefficients
virtual void getLnActivityCoefficients(doublereal *lnac) const
Get the array of non-dimensional molar-based ln activity coefficients at the current solution tempera...
Definition: ThermoPhase.cpp:83
Cantera::ThermoPhase::setState_SV
virtual void setState_SV(double s, double v, double tol=1e-9)
Set the specific entropy (J/kg/K) and specific volume (m^3/kg).
Definition: ThermoPhase.cpp:521
Cantera::MultiSpeciesThermo
A species thermodynamic property manager for a phase.
Definition: MultiSpeciesThermo.h:46
Cantera::Phase::setState_TR
void setState_TR(doublereal t, doublereal rho)
Set the internally stored temperature (K) and density (kg/m^3)
Definition: Phase.cpp:491
Cantera::ThermoPhase::cp_mass
doublereal cp_mass() const
Specific heat at constant pressure. Units: J/kg/K.
Definition: ThermoPhase.h:762
Cantera::ThermoPhase::o2Required
double o2Required(const double *y) const
Helper function for computing the amount of oxygen required for complete oxidation.
Definition: ThermoPhase.cpp:700
Cantera::Phase::m_kk
size_t m_kk
Number of species in the phase.
Definition: Phase.h:942
Cantera::Phase::charge
doublereal charge(size_t k) const
Dimensionless electrical charge of a single molecule of species k The charge is normalized by the the...
Definition: Phase.h:643
Cantera::ThermoPhase::addSpecies
virtual bool addSpecies(shared_ptr< Species > spec)
Definition: ThermoPhase.cpp:1134
Cantera::ThermoPhase::m_input
AnyMap m_input
Data supplied via setParameters.
Definition: ThermoPhase.h:1874
Cantera::Phase::molecularWeight
doublereal molecularWeight(size_t k) const
Molecular weight of species k.
Definition: Phase.cpp:521
Cantera::Phase::density
virtual double density() const
Density (kg/m^3).
Definition: Phase.h:685
Cantera::ThermoPhase::gibbs_mass
doublereal gibbs_mass() const
Specific Gibbs function. Units: J/kg.
Definition: ThermoPhase.h:757
Cantera::Phase::setMassFractions
virtual void setMassFractions(const double *const y)
Set the mass fractions to the specified values and normalize them.
Definition: Phase.cpp:420
Cantera::ThermoPhase::setState_RPX
virtual void setState_RPX(doublereal rho, doublereal p, const doublereal *x)
Set the density (kg/m**3), pressure (Pa) and mole fractions.
Definition: ThermoPhase.cpp:149
Cantera::Phase::setMassFractions_NoNorm
virtual void setMassFractions_NoNorm(const double *const y)
Set the mass fractions to the specified values without normalizing.
Definition: Phase.cpp:434
Cantera::ThermoPhase::report
virtual std::string report(bool show_thermo=true, doublereal threshold=-1e-14) const
returns a summary of the state of the phase as a string
Definition: ThermoPhase.cpp:1335
Cantera::Phase::nAtoms
doublereal nAtoms(size_t k, size_t m) const
Number of atoms of element m in species k.
Definition: Phase.cpp:168
Cantera::ThermoPhase::setEquivalenceRatio
void setEquivalenceRatio(double phi, const double *fuelComp, const double *oxComp, ThermoBasis basis=ThermoBasis::molar)
Set the mixture composition according to the equivalence ratio.
Definition: ThermoPhase.cpp:795
Cantera::Phase::molecularWeights
const vector_fp & molecularWeights() const
Return a const reference to the internal vector of molecular weights.
Definition: Phase.cpp:538
Cantera::ThermoPhase::speciesData
const std::vector< const XML_Node * > & speciesData() const
Return a pointer to the vector of XML nodes containing the species data for this phase.
Definition: ThermoPhase.cpp:1172
Cantera::ThermoPhase::setState_TV
virtual void setState_TV(double t, double v, double tol=1e-9)
Set the temperature (K) and specific volume (m^3/kg).
Definition: ThermoPhase.h:975
Cantera::MultiPhase::init
void init()
Process phases and build atomic composition array.
Definition: MultiPhase.cpp:116
Cantera::ThermoPhase::setState_TPX
virtual void setState_TPX(doublereal t, doublereal p, const doublereal *x)
Set the temperature (K), pressure (Pa), and mole fractions.
Definition: ThermoPhase.cpp:100
Cantera::ThermoPhase::setParameters
virtual void setParameters(int n, doublereal *const c)
Set the equation of state parameters.
Definition: ThermoPhase.h:1691
Cantera::setupPhase
void setupPhase(ThermoPhase &thermo, AnyMap &phaseNode, const AnyMap &rootNode)
Initialize a ThermoPhase object.
Definition: ThermoFactory.cpp:447
Cantera::ThermoPhase::setState_Tsat
virtual void setState_Tsat(doublereal t, doublereal x)
Set the state to a saturated system at a particular temperature.
Definition: ThermoPhase.h:1540
Cantera::ThermoPhase::input
const AnyMap & input() const
Access input data associated with the phase description.
Definition: ThermoPhase.cpp:1186
Cantera::ThermoPhase::reportCSV
virtual void reportCSV(std::ofstream &csvFile) const
returns a summary of the state of the phase to a comma separated file.
Definition: ThermoPhase.cpp:1448
Cantera::ThermoPhase::getPartialMolarCp
virtual void getPartialMolarCp(doublereal *cpbar) const
Return an array of partial molar heat capacities for the species in the mixture.
Definition: ThermoPhase.h:546
Cantera::ThermoPhase::maxTemp
virtual doublereal maxTemp(size_t k=npos) const
Maximum temperature for which the thermodynamic data for the species are valid.
Definition: ThermoPhase.h:213
Cantera::ThermoPhase::setState_RPY
virtual void setState_RPY(doublereal rho, doublereal p, const doublereal *y)
Set the density (kg/m**3), pressure (Pa) and mass fractions.
Definition: ThermoPhase.cpp:167
Cantera::debuglog
void debuglog(const std::string &msg, int loglevel)
Write a message to the log only if loglevel > 0.
Definition: global.h:140
Cantera::XML_Node
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:103
Cantera::AnyMap::fromYamlFile
static AnyMap fromYamlFile(const std::string &name, const std::string &parent_name="")
Create an AnyMap from a YAML file.
Definition: AnyMap.cpp:1156
Cantera::ThermoPhase::speciesThermo
virtual MultiSpeciesThermo & speciesThermo(int k=-1)
Return a changeable reference to the calculation manager for species reference-state thermodynamic pr...
Definition: ThermoPhase.cpp:1053
Cantera::ThermoPhase::m_tlast
doublereal m_tlast
last value of the temperature processed by reference state
Definition: ThermoPhase.h:1904
Cantera::Phase::saveState
void saveState(vector_fp &state) const
Save the current internal state of the phase.
Definition: Phase.cpp:315
Cantera::OneAtm
const double OneAtm
One atmosphere [Pa].
Definition: ct_defs.h:78
Cantera::Phase::restoreState
void restoreState(const vector_fp &state)
Restore a state saved on a previous call to saveState.
Definition: Phase.cpp:339
Cantera::ThermoPhase::setState_VH
virtual void setState_VH(double v, double h, double tol=1e-9)
Set the specific volume (m^3/kg) and the specific enthalpy (J/kg)
Definition: ThermoPhase.h:1023
Cantera::ThermoPhase::RT
doublereal RT() const
Return the Gas Constant multiplied by the current temperature.
Definition: ThermoPhase.h:776
Cantera::ThermoPhase::minTemp
virtual doublereal minTemp(size_t k=npos) const
Minimum temperature for which the thermodynamic data for the species or phase are valid.
Definition: ThermoPhase.h:160
Cantera::ThermoPhase::setState_SPorSV
void setState_SPorSV(double s, double p, double tol=1e-9, bool doSV=false)
Carry out work in SP and SV calculations.
Definition: ThermoPhase.cpp:527
Cantera::ThermoPhase::initThermoFile
virtual void initThermoFile(const std::string &inputFile, const std::string &id)
Definition: ThermoPhase.cpp:1064
Cantera::Phase::setMoleFractions
virtual void setMoleFractions(const double *const x)
Set the mole fractions to the specified values.
Definition: Phase.cpp:368
SpeciesThermoInterpType.h
Cantera::Phase::elementIndex
size_t elementIndex(const std::string &name) const
Return the index of element named 'name'.
Definition: Phase.cpp:120
ctml.h
Cantera::ThermoPhase::setState_HP
virtual void setState_HP(double h, double p, double tol=1e-9)
Set the internally stored specific enthalpy (J/kg) and pressure (Pa) of the phase.
Definition: ThermoPhase.cpp:197
Cantera::ThermoPhase::invalidateCache
virtual void invalidateCache()
Invalidate any cached values which are normally updated only when a change in state is detected.
Definition: ThermoPhase.cpp:1221
Cantera::Phase::moleFractionsToMassFractions
void moleFractionsToMassFractions(const double *X, double *Y) const
Converts a mixture composition from mass fractions to mole fractions.
Definition: Phase.cpp:1061
Cantera::ThermoPhase::satPressure
virtual doublereal satPressure(doublereal t)
Return the saturation pressure given the temperature.
Definition: ThermoPhase.h:1526
Cantera::ThermoPhase::getPartialMolarVolumes
virtual void getPartialMolarVolumes(doublereal *vbar) const
Return an array of partial molar volumes for the species in the mixture.
Definition: ThermoPhase.h:556
stringUtils.h
Cantera::ThermoPhase::entropy_mole
virtual doublereal entropy_mole() const
Molar entropy. Units: J/kmol/K.
Definition: ThermoPhase.h:244
Cantera::parseCompString
compositionMap parseCompString(const std::string &ss, const std::vector< std::string > &names)
Parse a composition string into a map consisting of individual key:composition pairs.
Definition: stringUtils.cpp:60
Cantera::Phase::pressure
virtual double pressure() const
Return the thermodynamic pressure (Pa).
Definition: Phase.h:679
Cantera::AnyMap::erase
void erase(const std::string &key)
Erase the value held by key.
Definition: AnyMap.cpp:989
Cantera::Phase::temperature
doublereal temperature() const
Temperature (K).
Definition: Phase.h:667
Cantera::ThermoPhase::saveSpeciesData
void saveSpeciesData(const size_t k, const XML_Node *const data)
Store a reference pointer to the XML tree containing the species data for this phase.
Definition: ThermoPhase.cpp:1164
Cantera::dot
doublereal dot(InputIter x_begin, InputIter x_end, InputIter2 y_begin)
Function that calculates a templated inner product.
Definition: utilities.h:112
Cantera::ThermoPhase::critPressure
virtual doublereal critPressure() const
Critical pressure (Pa).
Definition: ThermoPhase.h:1486
Cantera::Phase::nSpecies
size_t nSpecies() const
Returns the number of species in the phase.
Definition: Phase.h:285
Cantera::ThermoPhase::getCsvReportData
virtual void getCsvReportData(std::vector< std::string > &names, std::vector< vector_fp > &data) const
Fills names and data with the column names and species thermo properties to be included in the output...
Definition: ThermoPhase.cpp:1480
Cantera::MultiPhase::addPhase
void addPhase(ThermoPhase *p, doublereal moles)
Add a phase to the mixture.
Definition: MultiPhase.cpp:49
Cantera::ChemEquil::equilibrate
int equilibrate(thermo_t &s, const char *XY, int loglevel=0)
Definition: ChemEquil.cpp:308
Cantera::ThermoPhase::modifySpecies
virtual void modifySpecies(size_t k, shared_ptr< Species > spec)
Modify the thermodynamic data associated with a species.
Definition: ThermoPhase.cpp:1148
Cantera::ThermoPhase::m_spthermo
MultiSpeciesThermo m_spthermo
Pointer to the calculation manager for species reference-state thermodynamic properties.
Definition: ThermoPhase.h:1870
Cantera::ThermoPhase::phaseOfMatter
virtual std::string phaseOfMatter() const
String indicating the mechanical phase of the matter in this Phase.
Definition: ThermoPhase.h:137
Cantera::ThermoPhase::standardConcentrationUnits
virtual Units standardConcentrationUnits() const
Returns the units of the "standard concentration" for this phase.
Definition: ThermoPhase.cpp:64
Cantera::Phase::setDensity
virtual void setDensity(const double density_)
Set the internally stored density (kg/m^3) of the phase.
Definition: Phase.cpp:716
Cantera::getFloat
doublereal getFloat(const XML_Node &parent, const std::string &name, const std::string &type)
Get a floating-point value from a child element.
Definition: ctml.cpp:164
Cantera::Phase::getCompositionFromMap
vector_fp getCompositionFromMap(const compositionMap &comp) const
Converts a compositionMap to a vector with entries for each species Species that are not specified ar...
Definition: Phase.cpp:1032
Cantera::ThermoPhase::cv_mole
virtual doublereal cv_mole() const
Molar heat capacity at constant volume. Units: J/kmol/K.
Definition: ThermoPhase.h:259
Cantera::ThermoPhase::getPartialMolarEntropies
virtual void getPartialMolarEntropies(doublereal *sbar) const
Returns an array of partial molar entropies of the species in the solution.
Definition: ThermoPhase.h:525
Cantera::ThermoPhase::electricPotential
doublereal electricPotential() const
Returns the electric potential of this phase (V).
Definition: ThermoPhase.h:320
Cantera::Units
A representation of the units associated with a dimensional quantity.
Definition: Units.h:29
Cantera::ThermoPhase::gibbs_mole
virtual doublereal gibbs_mole() const
Molar Gibbs function. Units: J/kmol.
Definition: ThermoPhase.h:249
Cantera::ThermoPhase::getChemPotentials
virtual void getChemPotentials(doublereal *mu) const
Get the species chemical potentials. Units: J/kmol.
Definition: ThermoPhase.h:489
Cantera::ThermoPhase::setMixtureFraction
void setMixtureFraction(double mixFrac, const double *fuelComp, const double *oxComp, ThermoBasis basis=ThermoBasis::molar)
Set the mixture composition according to the mixture fraction = kg fuel / (kg oxidizer + kg fuel)
Definition: ThermoPhase.cpp:923
Cantera::ThermoPhase::setState_UP
virtual void setState_UP(double u, double p, double tol=1e-9)
Set the specific internal energy (J/kg) and pressure (Pa).
Definition: ThermoPhase.h:1007
Cantera::AnyMap
A map of string keys to values whose type can vary at runtime.
Definition: AnyMap.h:359
Cantera::ThermoPhase::o2Present
double o2Present(const double *y) const
Helper function for computing the amount of oxygen available in the current mixture.
Definition: ThermoPhase.cpp:729
Cantera::ThermoPhase::setState_TPQ
void setState_TPQ(double T, double P, double Q)
Set the temperature, pressure, and vapor fraction (quality).
Definition: ThermoPhase.cpp:1105
Cantera::Faraday
const double Faraday
Faraday constant [C/kmol].
Definition: ct_defs.h:123
MultiPhase.h
Cantera::ThermoPhase::m_speciesData
std::vector< const XML_Node * > m_speciesData
Vector of pointers to the species databases.
Definition: ThermoPhase.h:1885
Cantera::ThermoPhase::setState_ST
virtual void setState_ST(double s, double t, double tol=1e-9)
Set the specific entropy (J/kg/K) and temperature (K).
Definition: ThermoPhase.h:959
Cantera::CanteraError
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:60
Cantera::ThermoPhase::setState_Psat
virtual void setState_Psat(doublereal p, doublereal x)
Set the state to a saturated system at a particular pressure.
Definition: ThermoPhase.h:1549
Cantera::importPhase
void importPhase(XML_Node &phase, ThermoPhase *th)
Import a phase information into an empty ThermoPhase object.
Definition: ThermoFactory.cpp:237
Cantera::Phase::getMassFractions
void getMassFractions(double *const y) const
Get the species mass fractions.
Definition: Phase.cpp:614
Cantera::ThermoPhase::setState_PV
virtual void setState_PV(double p, double v, double tol=1e-9)
Set the pressure (Pa) and specific volume (m^3/kg).
Definition: ThermoPhase.h:991
Cantera::ThermoPhase::setState_TH
virtual void setState_TH(double t, double h, double tol=1e-9)
Set the temperature (K) and the specific enthalpy (J/kg)
Definition: ThermoPhase.h:1039
Cantera::npos
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:188
Cantera::ThermoPhase::m_ssConvention
int m_ssConvention
Contains the standard state convention.
Definition: ThermoPhase.h:1901
Cantera::EquilOpt::maxIterations
int maxIterations
Maximum number of iterations.
Definition: ChemEquil.h:36
Cantera::ThermoPhase::entropy_mass
doublereal entropy_mass() const
Specific entropy. Units: J/kg/K.
Definition: ThermoPhase.h:752
Cantera::ThermoPhase::initThermo
virtual void initThermo()
Initialize the ThermoPhase object after all species have been set up.
Definition: ThermoPhase.cpp:1096
Cantera::ThermoPhase::setState_HPorUV
void setState_HPorUV(doublereal h, doublereal p, doublereal tol=1e-9, bool doUV=false)
Carry out work in HP and UV calculations.
Definition: ThermoPhase.cpp:325
Cantera
Namespace for the Cantera kernel.
Definition: AnyMap.cpp:263
Cantera::Phase::speciesName
std::string speciesName(size_t k) const
Name of the species with index k.
Definition: Phase.cpp:229
Cantera::MultiSpeciesThermo::install_STIT
virtual void install_STIT(size_t index, shared_ptr< SpeciesThermoInterpType > stit)
Install a new species thermodynamic property parameterization for one species.
Definition: MultiSpeciesThermo.cpp:26
Cantera::ThermoPhase::critTemperature
virtual doublereal critTemperature() const
Critical temperature (K).
Definition: ThermoPhase.h:1481
Cantera::ThermoPhase::setState_conditional_TP
void setState_conditional_TP(doublereal t, doublereal p, bool set_p)
Helper function used by setState_HPorUV and setState_SPorSV.
Definition: ThermoPhase.cpp:317
Cantera::XML_Node::child
XML_Node & child(const size_t n) const
Return a changeable reference to the n'th child of the current node.
Definition: xml.cpp:546
Cantera::ThermoPhase::getActivityConcentrations
virtual void getActivityConcentrations(doublereal *c) const
This method returns an array of generalized concentrations.
Definition: ThermoPhase.h:398
ThermoPhase.h
Cantera::ThermoPhase::logStandardConc
virtual doublereal logStandardConc(size_t k=0) const
Natural logarithm of the standard concentration of the kth species.
Definition: ThermoPhase.cpp:70
Cantera::AnyMap::size
size_t size() const
Returns the number of elements in this map.
Definition: AnyMap.h:484
Cantera::ThermoPhase::resetHf298
virtual void resetHf298(const size_t k=npos)
Restore the original heat of formation of one or more species.
Definition: ThermoPhase.cpp:43
Cantera::Phase::setMoleFractionsByName
void setMoleFractionsByName(const compositionMap &xMap)
Set the species mole fractions by name.
Definition: Phase.cpp:409
Cantera::AnyMap::keys_str
std::string keys_str() const
Return a string listing the keys in this AnyMap, e.g.
Definition: AnyMap.cpp:999
Cantera::ThermoPhase::setState_RP
virtual void setState_RP(doublereal rho, doublereal p)
Set the density (kg/m**3) and pressure (Pa) at constant composition.
Definition: ThermoPhase.h:1072