Cantera  2.5.1
MixtureFugacityTP.cpp
Go to the documentation of this file.
1 /**
2  * @file MixtureFugacityTP.cpp
3  * Methods file for a derived class of ThermoPhase that handles
4  * non-ideal mixtures based on the fugacity models (see \ref thermoprops and
5  * class \link Cantera::MixtureFugacityTP MixtureFugacityTP\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 
13 #include "cantera/base/ctml.h"
14 
15 using namespace std;
16 
17 namespace Cantera
18 {
19 
20 MixtureFugacityTP::MixtureFugacityTP() :
21  iState_(FLUID_GAS),
22  forcedState_(FLUID_UNDEFINED),
23  m_Tlast_ref(-1.0)
24 {
25 }
26 
28 {
30 }
31 
33 {
34  forcedState_ = solnBranch;
35 }
36 
38 {
39  return forcedState_;
40 }
41 
43 {
44  return iState_;
45 }
46 
47 // ---- Partial Molar Properties of the Solution -----------------
48 
49 void MixtureFugacityTP::getChemPotentials_RT(doublereal* muRT) const
50 {
51  getChemPotentials(muRT);
52  for (size_t k = 0; k < m_kk; k++) {
53  muRT[k] *= 1.0 / RT();
54  }
55 }
56 
57 // ----- Thermodynamic Values for the Species Standard States States ----
58 
60 {
62  copy(m_g0_RT.begin(), m_g0_RT.end(), g);
63  double tmp = log(pressure() / refPressure());
64  for (size_t k = 0; k < m_kk; k++) {
65  g[k] = RT() * (g[k] + tmp);
66  }
67 }
68 
69 void MixtureFugacityTP::getEnthalpy_RT(doublereal* hrt) const
70 {
71  getEnthalpy_RT_ref(hrt);
72 }
73 
74 void MixtureFugacityTP::getEntropy_R(doublereal* sr) const
75 {
77  copy(m_s0_R.begin(), m_s0_R.end(), sr);
78  double tmp = log(pressure() / refPressure());
79  for (size_t k = 0; k < m_kk; k++) {
80  sr[k] -= tmp;
81  }
82 }
83 
84 void MixtureFugacityTP::getGibbs_RT(doublereal* grt) const
85 {
87  copy(m_g0_RT.begin(), m_g0_RT.end(), grt);
88  double tmp = log(pressure() / refPressure());
89  for (size_t k = 0; k < m_kk; k++) {
90  grt[k] += tmp;
91  }
92 }
93 
94 void MixtureFugacityTP::getPureGibbs(doublereal* g) const
95 {
97  scale(m_g0_RT.begin(), m_g0_RT.end(), g, RT());
98  double tmp = log(pressure() / refPressure()) * RT();
99  for (size_t k = 0; k < m_kk; k++) {
100  g[k] += tmp;
101  }
102 }
103 
104 void MixtureFugacityTP::getIntEnergy_RT(doublereal* urt) const
105 {
107  copy(m_h0_RT.begin(), m_h0_RT.end(), urt);
108  for (size_t i = 0; i < m_kk; i++) {
109  urt[i] -= 1.0;
110  }
111 }
112 
113 void MixtureFugacityTP::getCp_R(doublereal* cpr) const
114 {
116  copy(m_cp0_R.begin(), m_cp0_R.end(), cpr);
117 }
118 
119 void MixtureFugacityTP::getStandardVolumes(doublereal* vol) const
120 {
122  for (size_t i = 0; i < m_kk; i++) {
123  vol[i] = RT() / pressure();
124  }
125 }
126 
127 // ----- Thermodynamic Values for the Species Reference States ----
128 
129 void MixtureFugacityTP::getEnthalpy_RT_ref(doublereal* hrt) const
130 {
132  copy(m_h0_RT.begin(), m_h0_RT.end(), hrt);
133 }
134 
135 void MixtureFugacityTP::getGibbs_RT_ref(doublereal* grt) const
136 {
138  copy(m_g0_RT.begin(), m_g0_RT.end(), grt);
139 }
140 
141 void MixtureFugacityTP::getGibbs_ref(doublereal* g) const
142 {
143  const vector_fp& gibbsrt = gibbs_RT_ref();
144  scale(gibbsrt.begin(), gibbsrt.end(), g, RT());
145 }
146 
148 {
150  return m_g0_RT;
151 }
152 
153 void MixtureFugacityTP::getEntropy_R_ref(doublereal* er) const
154 {
156  copy(m_s0_R.begin(), m_s0_R.end(), er);
157 }
158 
159 void MixtureFugacityTP::getCp_R_ref(doublereal* cpr) const
160 {
162  copy(m_cp0_R.begin(), m_cp0_R.end(), cpr);
163 }
164 
165 void MixtureFugacityTP::getStandardVolumes_ref(doublereal* vol) const
166 {
168  for (size_t i = 0; i < m_kk; i++) {
169  vol[i]= RT() / refPressure();
170  }
171 }
172 
174 {
175  int doTP = 0;
176  string comp = getChildValue(state,"moleFractions");
177  if (comp != "") {
178  // not overloaded in current object -> phase state is not calculated.
180  doTP = 1;
181  } else {
182  comp = getChildValue(state,"massFractions");
183  if (comp != "") {
184  // not overloaded in current object -> phase state is not calculated.
186  doTP = 1;
187  }
188  }
189  double t = temperature();
190  if (state.hasChild("temperature")) {
191  t = getFloat(state, "temperature", "temperature");
192  doTP = 1;
193  }
194  if (state.hasChild("pressure")) {
195  double p = getFloat(state, "pressure", "pressure");
196  setState_TP(t, p);
197  } else if (state.hasChild("density")) {
198  double rho = getFloat(state, "density", "density");
199  setState_TR(t, rho);
200  } else if (doTP) {
201  double rho = Phase::density();
202  setState_TR(t, rho);
203  }
204 }
205 
206 bool MixtureFugacityTP::addSpecies(shared_ptr<Species> spec)
207 {
208  bool added = ThermoPhase::addSpecies(spec);
209  if (added) {
210  if (m_kk == 1) {
211  moleFractions_.push_back(1.0);
212  } else {
213  moleFractions_.push_back(0.0);
214  }
215  m_h0_RT.push_back(0.0);
216  m_cp0_R.push_back(0.0);
217  m_g0_RT.push_back(0.0);
218  m_s0_R.push_back(0.0);
219  }
220  return added;
221 }
222 
223 void MixtureFugacityTP::setTemperature(const doublereal temp)
224 {
226  setState_TR(temperature(), density());
227 }
228 
230 {
231  setState_TP(temperature(), p);
232  }
233 
235 {
238 }
239 
240 void MixtureFugacityTP::setMoleFractions_NoState(const doublereal* const x)
241 {
244  updateMixingExpressions();
245 }
246 
248 {
249  throw NotImplementedError("MixtureFugacityTP::calcDensity");
250 }
251 
252 void MixtureFugacityTP::setState_TP(doublereal t, doublereal pres)
253 {
254  // A pretty tricky algorithm is needed here, due to problems involving
255  // standard states of real fluids. For those cases you need to combine the T
256  // and P specification for the standard state, or else you may venture into
257  // the forbidden zone, especially when nearing the triple point. Therefore,
258  // we need to do the standard state thermo calc with the (t, pres) combo.
260 
263  // Depends on the mole fractions and the temperature
264  updateMixingExpressions();
265 
266  if (forcedState_ == FLUID_UNDEFINED) {
267  double rhoNow = Phase::density();
268  double rho = densityCalc(t, pres, iState_, rhoNow);
269  if (rho > 0.0) {
270  Phase::setDensity(rho);
271  iState_ = phaseState(true);
272  } else {
273  if (rho < -1.5) {
274  rho = densityCalc(t, pres, FLUID_UNDEFINED , rhoNow);
275  if (rho > 0.0) {
276  Phase::setDensity(rho);
277  iState_ = phaseState(true);
278  } else {
279  throw CanteraError("MixtureFugacityTP::setState_TP", "neg rho");
280  }
281  } else {
282  throw CanteraError("MixtureFugacityTP::setState_TP", "neg rho");
283  }
284  }
285  } else if (forcedState_ == FLUID_GAS) {
286  // Normal density calculation
287  if (iState_ < FLUID_LIQUID_0) {
288  double rhoNow = Phase::density();
289  double rho = densityCalc(t, pres, iState_, rhoNow);
290  if (rho > 0.0) {
291  Phase::setDensity(rho);
292  iState_ = phaseState(true);
293  if (iState_ >= FLUID_LIQUID_0) {
294  throw CanteraError("MixtureFugacityTP::setState_TP", "wrong state");
295  }
296  } else {
297  throw CanteraError("MixtureFugacityTP::setState_TP", "neg rho");
298  }
299  }
300  } else if (forcedState_ > FLUID_LIQUID_0) {
301  if (iState_ >= FLUID_LIQUID_0) {
302  double rhoNow = Phase::density();
303  double rho = densityCalc(t, pres, iState_, rhoNow);
304  if (rho > 0.0) {
305  Phase::setDensity(rho);
306  iState_ = phaseState(true);
307  if (iState_ == FLUID_GAS) {
308  throw CanteraError("MixtureFugacityTP::setState_TP", "wrong state");
309  }
310  } else {
311  throw CanteraError("MixtureFugacityTP::setState_TP", "neg rho");
312  }
313  }
314  }
315 }
316 
317 void MixtureFugacityTP::setState_TR(doublereal T, doublereal rho)
318 {
322  Phase::setDensity(rho);
323  // depends on mole fraction and temperature
324  updateMixingExpressions();
325  iState_ = phaseState(true);
326 }
327 
328 void MixtureFugacityTP::setState_TPX(doublereal t, doublereal p, const doublereal* x)
329 {
330  setMoleFractions_NoState(x);
331  setState_TP(t,p);
332 }
333 
334 doublereal MixtureFugacityTP::z() const
335 {
336  return pressure() * meanMolecularWeight() / (density() * RT());
337 }
338 
339 doublereal MixtureFugacityTP::sresid() const
340 {
341  throw NotImplementedError("MixtureFugacityTP::sresid");
342 }
343 
344 doublereal MixtureFugacityTP::hresid() const
345 {
346  throw NotImplementedError("MixtureFugacityTP::hresid");
347 }
348 
349 doublereal MixtureFugacityTP::psatEst(doublereal TKelvin) const
350 {
351  doublereal pcrit = critPressure();
352  doublereal tt = critTemperature() / TKelvin;
353  if (tt < 1.0) {
354  return pcrit;
355  }
356  doublereal lpr = -0.8734*tt*tt - 3.4522*tt + 4.2918;
357  return pcrit*exp(lpr);
358 }
359 
360 doublereal MixtureFugacityTP::liquidVolEst(doublereal TKelvin, doublereal& pres) const
361 {
362  throw NotImplementedError("MixtureFugacityTP::liquidVolEst");
363 }
364 
365 doublereal MixtureFugacityTP::densityCalc(doublereal TKelvin, doublereal presPa,
366  int phase, doublereal rhoguess)
367 {
368  doublereal tcrit = critTemperature();
369  doublereal mmw = meanMolecularWeight();
370  if (rhoguess == -1.0) {
371  if (phase != -1) {
372  if (TKelvin > tcrit) {
373  rhoguess = presPa * mmw / (GasConstant * TKelvin);
374  } else {
375  if (phase == FLUID_GAS || phase == FLUID_SUPERCRIT) {
376  rhoguess = presPa * mmw / (GasConstant * TKelvin);
377  } else if (phase >= FLUID_LIQUID_0) {
378  double lqvol = liquidVolEst(TKelvin, presPa);
379  rhoguess = mmw / lqvol;
380  }
381  }
382  } else {
383  // Assume the Gas phase initial guess, if nothing is specified to
384  // the routine
385  rhoguess = presPa * mmw / (GasConstant * TKelvin);
386  }
387  }
388 
389  double molarVolBase = mmw / rhoguess;
390  double molarVolLast = molarVolBase;
391  double vc = mmw / critDensity();
392 
393  // molar volume of the spinodal at the current temperature and mole
394  // fractions. this will be updated as we go.
395  double molarVolSpinodal = vc;
396  bool conv = false;
397 
398  // We start on one side of the vc and stick with that side
399  bool gasSide = molarVolBase > vc;
400  if (gasSide) {
401  molarVolLast = (GasConstant * TKelvin)/presPa;
402  } else {
403  molarVolLast = liquidVolEst(TKelvin, presPa);
404  }
405 
406  // OK, now we do a small solve to calculate the molar volume given the T,P
407  // value. The algorithm is taken from dfind()
408  for (int n = 0; n < 200; n++) {
409  // Calculate the predicted reduced pressure, pred0, based on the current
410  // tau and dd. Calculate the derivative of the predicted pressure wrt
411  // the molar volume. This routine also returns the pressure, presBase
412  double presBase;
413  double dpdVBase = dpdVCalc(TKelvin, molarVolBase, presBase);
414 
415  // If dpdV is positive, then we are in the middle of the 2 phase region
416  // and beyond the spinodal stability curve. We need to adjust the
417  // initial guess outwards and start a new iteration.
418  if (dpdVBase >= 0.0) {
419  if (TKelvin > tcrit) {
420  throw CanteraError("MixtureFugacityTP::densityCalc",
421  "T > tcrit unexpectedly");
422  }
423 
424  // TODO Spawn a calculation for the value of the spinodal point that
425  // is very accurate. Answer the question as to whether a
426  // solution is possible on the current side of the vapor dome.
427  if (gasSide) {
428  if (molarVolBase >= vc) {
429  molarVolSpinodal = molarVolBase;
430  molarVolBase = 0.5 * (molarVolLast + molarVolSpinodal);
431  } else {
432  molarVolBase = 0.5 * (molarVolLast + molarVolSpinodal);
433  }
434  } else {
435  if (molarVolBase <= vc) {
436  molarVolSpinodal = molarVolBase;
437  molarVolBase = 0.5 * (molarVolLast + molarVolSpinodal);
438  } else {
439  molarVolBase = 0.5 * (molarVolLast + molarVolSpinodal);
440  }
441  }
442  continue;
443  }
444 
445  // Check for convergence
446  if (fabs(presBase-presPa) < 1.0E-30 + 1.0E-8 * presPa) {
447  conv = true;
448  break;
449  }
450 
451  // Dampen and crop the update
452  doublereal dpdV = dpdVBase;
453  if (n < 10) {
454  dpdV = dpdVBase * 1.5;
455  }
456 
457  // Formulate the update to the molar volume by Newton's method. Then,
458  // crop it to a max value of 0.1 times the current volume
459  double delMV = - (presBase - presPa) / dpdV;
460  if ((!gasSide || delMV < 0.0) && fabs(delMV) > 0.2 * molarVolBase) {
461  delMV = delMV / fabs(delMV) * 0.2 * molarVolBase;
462  }
463  // Only go 1/10 the way towards the spinodal at any one time.
464  if (TKelvin < tcrit) {
465  if (gasSide) {
466  if (delMV < 0.0 && -delMV > 0.5 * (molarVolBase - molarVolSpinodal)) {
467  delMV = - 0.5 * (molarVolBase - molarVolSpinodal);
468  }
469  } else {
470  if (delMV > 0.0 && delMV > 0.5 * (molarVolSpinodal - molarVolBase)) {
471  delMV = 0.5 * (molarVolSpinodal - molarVolBase);
472  }
473  }
474  }
475  // updated the molar volume value
476  molarVolLast = molarVolBase;
477  molarVolBase += delMV;
478 
479  if (fabs(delMV/molarVolBase) < 1.0E-14) {
480  conv = true;
481  break;
482  }
483 
484  // Check for negative molar volumes
485  if (molarVolBase <= 0.0) {
486  molarVolBase = std::min(1.0E-30, fabs(delMV*1.0E-4));
487  }
488  }
489 
490  // Check for convergence, and return 0.0 if it wasn't achieved.
491  double densBase = 0.0;
492  if (! conv) {
493  molarVolBase = 0.0;
494  throw CanteraError("MixtureFugacityTP::densityCalc", "Process did not converge");
495  } else {
496  densBase = mmw / molarVolBase;
497  }
498  return densBase;
499 }
500 
501 void MixtureFugacityTP::updateMixingExpressions()
502 {
503 }
504 
505 int MixtureFugacityTP::corr0(doublereal TKelvin, doublereal pres, doublereal& densLiqGuess,
506  doublereal& densGasGuess, doublereal& liqGRT, doublereal& gasGRT)
507 {
508  int retn = 0;
509  doublereal densLiq = densityCalc(TKelvin, pres, FLUID_LIQUID_0, densLiqGuess);
510  if (densLiq <= 0.0) {
511  retn = -1;
512  } else {
513  densLiqGuess = densLiq;
514  setState_TR(TKelvin, densLiq);
515  liqGRT = gibbs_mole() / RT();
516  }
517 
518  doublereal densGas = densityCalc(TKelvin, pres, FLUID_GAS, densGasGuess);
519  if (densGas <= 0.0) {
520  if (retn == -1) {
521  throw CanteraError("MixtureFugacityTP::corr0",
522  "Error occurred trying to find gas density at (T,P) = {} {}",
523  TKelvin, pres);
524  }
525  retn = -2;
526  } else {
527  densGasGuess = densGas;
528  setState_TR(TKelvin, densGas);
529  gasGRT = gibbs_mole() / RT();
530  }
531  return retn;
532 }
533 
534 int MixtureFugacityTP::phaseState(bool checkState) const
535 {
536  int state = iState_;
537  if (checkState) {
538  double t = temperature();
539  double tcrit = critTemperature();
540  double rhocrit = critDensity();
541  if (t >= tcrit) {
542  return FLUID_SUPERCRIT;
543  }
544  double tmid = tcrit - 100.;
545  if (tmid < 0.0) {
546  tmid = tcrit / 2.0;
547  }
548  double pp = psatEst(tmid);
549  double mmw = meanMolecularWeight();
550  double molVolLiqTmid = liquidVolEst(tmid, pp);
551  double molVolGasTmid = GasConstant * tmid / pp;
552  double densLiqTmid = mmw / molVolLiqTmid;
553  double densGasTmid = mmw / molVolGasTmid;
554  double densMidTmid = 0.5 * (densLiqTmid + densGasTmid);
555  doublereal rhoMid = rhocrit + (t - tcrit) * (rhocrit - densMidTmid) / (tcrit - tmid);
556 
557  double rho = density();
558  int iStateGuess = FLUID_LIQUID_0;
559  if (rho < rhoMid) {
560  iStateGuess = FLUID_GAS;
561  }
562  double molarVol = mmw / rho;
563  double presCalc;
564 
565  double dpdv = dpdVCalc(t, molarVol, presCalc);
566  if (dpdv < 0.0) {
567  state = iStateGuess;
568  } else {
569  state = FLUID_UNSTABLE;
570  }
571  }
572  return state;
573 }
574 
576 {
577  throw NotImplementedError("MixtureFugacityTP::densSpinodalLiquid");
578 }
579 
581 {
582  throw NotImplementedError("MixtureFugacityTP::densSpinodalGas");
583 }
584 
585 doublereal MixtureFugacityTP::satPressure(doublereal TKelvin)
586 {
587  doublereal molarVolGas;
588  doublereal molarVolLiquid;
589  return calculatePsat(TKelvin, molarVolGas, molarVolLiquid);
590 }
591 
592 doublereal MixtureFugacityTP::calculatePsat(doublereal TKelvin, doublereal& molarVolGas,
593  doublereal& molarVolLiquid)
594 {
595  // The algorithm for this routine has undergone quite a bit of work. It
596  // probably needs more work. However, it seems now to be fairly robust. The
597  // key requirement is to find an initial pressure where both the liquid and
598  // the gas exist. This is not as easy as it sounds, and it gets exceedingly
599  // hard as the critical temperature is approached from below. Once we have
600  // this initial state, then we seek to equilibrate the Gibbs free energies
601  // of the gas and liquid and use the formula
602  //
603  // dp = VdG
604  //
605  // to create an update condition for deltaP using
606  //
607  // - (Gliq - Ggas) = (Vliq - Vgas) (deltaP)
608  //
609  // @TODO Suggestions for the future would be to switch it to an algorithm
610  // that uses the gas molar volume and the liquid molar volumes as the
611  // fundamental unknowns.
612 
613  // we need this because this is a non-const routine that is public
614  setTemperature(TKelvin);
615  double densSave = density();
616  double tempSave = temperature();
617  double pres;
618  doublereal mw = meanMolecularWeight();
619  if (TKelvin < critTemperature()) {
620  pres = psatEst(TKelvin);
621  // trial value = Psat from correlation
622  doublereal volLiquid = liquidVolEst(TKelvin, pres);
623  double RhoLiquidGood = mw / volLiquid;
624  double RhoGasGood = pres * mw / (GasConstant * TKelvin);
625  doublereal delGRT = 1.0E6;
626  doublereal liqGRT, gasGRT;
627 
628  // First part of the calculation involves finding a pressure at which
629  // the gas and the liquid state coexists.
630  doublereal presLiquid = 0.;
631  doublereal presGas;
632  doublereal presBase = pres;
633  bool foundLiquid = false;
634  bool foundGas = false;
635 
636  doublereal densLiquid = densityCalc(TKelvin, presBase, FLUID_LIQUID_0, RhoLiquidGood);
637  if (densLiquid > 0.0) {
638  foundLiquid = true;
639  presLiquid = pres;
640  RhoLiquidGood = densLiquid;
641  }
642  if (!foundLiquid) {
643  for (int i = 0; i < 50; i++) {
644  pres = 1.1 * pres;
645  densLiquid = densityCalc(TKelvin, pres, FLUID_LIQUID_0, RhoLiquidGood);
646  if (densLiquid > 0.0) {
647  foundLiquid = true;
648  presLiquid = pres;
649  RhoLiquidGood = densLiquid;
650  break;
651  }
652  }
653  }
654 
655  pres = presBase;
656  doublereal densGas = densityCalc(TKelvin, pres, FLUID_GAS, RhoGasGood);
657  if (densGas <= 0.0) {
658  foundGas = false;
659  } else {
660  foundGas = true;
661  presGas = pres;
662  RhoGasGood = densGas;
663  }
664  if (!foundGas) {
665  for (int i = 0; i < 50; i++) {
666  pres = 0.9 * pres;
667  densGas = densityCalc(TKelvin, pres, FLUID_GAS, RhoGasGood);
668  if (densGas > 0.0) {
669  foundGas = true;
670  presGas = pres;
671  RhoGasGood = densGas;
672  break;
673  }
674  }
675  }
676 
677  if (foundGas && foundLiquid && presGas != presLiquid) {
678  pres = 0.5 * (presLiquid + presGas);
679  bool goodLiq;
680  bool goodGas;
681  for (int i = 0; i < 50; i++) {
682  densLiquid = densityCalc(TKelvin, pres, FLUID_LIQUID_0, RhoLiquidGood);
683  if (densLiquid <= 0.0) {
684  goodLiq = false;
685  } else {
686  goodLiq = true;
687  RhoLiquidGood = densLiquid;
688  presLiquid = pres;
689  }
690  densGas = densityCalc(TKelvin, pres, FLUID_GAS, RhoGasGood);
691  if (densGas <= 0.0) {
692  goodGas = false;
693  } else {
694  goodGas = true;
695  RhoGasGood = densGas;
696  presGas = pres;
697  }
698  if (goodGas && goodLiq) {
699  break;
700  }
701  if (!goodLiq && !goodGas) {
702  pres = 0.5 * (pres + presLiquid);
703  }
704  if (goodLiq || goodGas) {
705  pres = 0.5 * (presLiquid + presGas);
706  }
707  }
708  }
709  if (!foundGas || !foundLiquid) {
710  warn_user("MixtureFugacityTP::calculatePsat",
711  "could not find a starting pressure; exiting.");
712  return 0.0;
713  }
714  if (presGas != presLiquid) {
715  warn_user("MixtureFugacityTP::calculatePsat",
716  "could not find a starting pressure; exiting");
717  return 0.0;
718  }
719 
720  pres = presGas;
721  double presLast = pres;
722  double RhoGas = RhoGasGood;
723  double RhoLiquid = RhoLiquidGood;
724 
725  // Now that we have found a good pressure we can proceed with the algorithm.
726  for (int i = 0; i < 20; i++) {
727  int stab = corr0(TKelvin, pres, RhoLiquid, RhoGas, liqGRT, gasGRT);
728  if (stab == 0) {
729  presLast = pres;
730  delGRT = liqGRT - gasGRT;
731  doublereal delV = mw * (1.0/RhoLiquid - 1.0/RhoGas);
732  doublereal dp = - delGRT * GasConstant * TKelvin / delV;
733 
734  if (fabs(dp) > 0.1 * pres) {
735  if (dp > 0.0) {
736  dp = 0.1 * pres;
737  } else {
738  dp = -0.1 * pres;
739  }
740  }
741  pres += dp;
742  } else if (stab == -1) {
743  delGRT = 1.0E6;
744  if (presLast > pres) {
745  pres = 0.5 * (presLast + pres);
746  } else {
747  // we are stuck here - try this
748  pres = 1.1 * pres;
749  }
750  } else if (stab == -2) {
751  if (presLast < pres) {
752  pres = 0.5 * (presLast + pres);
753  } else {
754  // we are stuck here - try this
755  pres = 0.9 * pres;
756  }
757  }
758  molarVolGas = mw / RhoGas;
759  molarVolLiquid = mw / RhoLiquid;
760 
761  if (fabs(delGRT) < 1.0E-8) {
762  // converged
763  break;
764  }
765  }
766 
767  molarVolGas = mw / RhoGas;
768  molarVolLiquid = mw / RhoLiquid;
769  // Put the fluid in the desired end condition
770  setState_TR(tempSave, densSave);
771  return pres;
772  } else {
773  pres = critPressure();
774  setState_TP(TKelvin, pres);
775  molarVolGas = mw / density();
776  molarVolLiquid = molarVolGas;
777  setState_TR(tempSave, densSave);
778  }
779  return pres;
780 }
781 
782 doublereal MixtureFugacityTP::pressureCalc(doublereal TKelvin, doublereal molarVol) const
783 {
784  throw NotImplementedError("MixtureFugacityTP::pressureCalc");
785 }
786 
787 doublereal MixtureFugacityTP::dpdVCalc(doublereal TKelvin, doublereal molarVol, doublereal& presCalc) const
788 {
789  throw NotImplementedError("MixtureFugacityTP::dpdVCalc");
790 }
791 
793 {
794  double Tnow = temperature();
795 
796  // If the temperature has changed since the last time these
797  // properties were computed, recompute them.
798  if (m_Tlast_ref != Tnow) {
799  m_spthermo.update(Tnow, &m_cp0_R[0], &m_h0_RT[0], &m_s0_R[0]);
800  m_Tlast_ref = Tnow;
801 
802  // update the species Gibbs functions
803  for (size_t k = 0; k < m_kk; k++) {
804  m_g0_RT[k] = m_h0_RT[k] - m_s0_R[k];
805  }
806  doublereal pref = refPressure();
807  if (pref <= 0.0) {
808  throw CanteraError("MixtureFugacityTP::_updateReferenceStateThermo", "neg ref pressure");
809  }
810  }
811 }
812 
814 {
816  m_Tlast_ref += 0.001234;
817 }
818 
819 }
Cantera::MixtureFugacityTP::getCp_R_ref
virtual void getCp_R_ref(doublereal *cprt) const
Returns the vector of nondimensional constant pressure heat capacities of the reference state at the ...
Definition: MixtureFugacityTP.cpp:159
FLUID_UNSTABLE
#define FLUID_UNSTABLE
Various states of the Fugacity object.
Definition: MixtureFugacityTP.h:22
Cantera::Phase::setMassFractionsByName
void setMassFractionsByName(const compositionMap &yMap)
Set the species mass fractions by name.
Definition: Phase.cpp:445
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::getMoleFractions
void getMoleFractions(double *const x) const
Get the species mole fraction vector.
Definition: Phase.cpp:572
Cantera::MixtureFugacityTP::getStandardChemPotentials
virtual void getStandardChemPotentials(doublereal *mu) const
Get the array of chemical potentials at unit activity.
Definition: MixtureFugacityTP.cpp:59
Cantera::ThermoPhase::refPressure
virtual doublereal refPressure() const
Returns the reference pressure in Pa.
Definition: ThermoPhase.h:145
Cantera::MixtureFugacityTP::densSpinodalGas
virtual doublereal densSpinodalGas() const
Return the value of the density at the gas spinodal point (on the gas side) for the current temperatu...
Definition: MixtureFugacityTP.cpp:580
Cantera::MixtureFugacityTP::setForcedSolutionBranch
virtual void setForcedSolutionBranch(int solnBranch)
Set the solution branch to force the ThermoPhase to exist on one branch or another.
Definition: MixtureFugacityTP.cpp:32
Cantera::MixtureFugacityTP::setPressure
virtual void setPressure(doublereal p)
Set the internally stored pressure (Pa) at constant temperature and composition.
Definition: MixtureFugacityTP.cpp:229
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::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::MixtureFugacityTP::getEntropy_R_ref
virtual void getEntropy_R_ref(doublereal *er) const
Returns the vector of nondimensional entropies of the reference state at the current temperature of t...
Definition: MixtureFugacityTP.cpp:153
Cantera::MixtureFugacityTP::m_Tlast_ref
doublereal m_Tlast_ref
The last temperature at which the reference state thermodynamic properties were calculated at.
Definition: MixtureFugacityTP.h:561
Cantera::MixtureFugacityTP::compositionChanged
virtual void compositionChanged()
Apply changes to the state which are needed after the composition changes.
Definition: MixtureFugacityTP.cpp:234
Cantera::cSS_CONVENTION_TEMPERATURE
const int cSS_CONVENTION_TEMPERATURE
Standard state uses the molar convention.
Definition: ThermoPhase.h:36
Cantera::MixtureFugacityTP::pressureCalc
virtual doublereal pressureCalc(doublereal TKelvin, doublereal molarVol) const
Calculate the pressure given the temperature and the molar volume.
Definition: MixtureFugacityTP.cpp:782
Cantera::MultiSpeciesThermo::update
virtual void update(doublereal T, doublereal *cp_R, doublereal *h_RT, doublereal *s_R) const
Compute the reference-state properties for all species.
Definition: MultiSpeciesThermo.cpp:90
Cantera::MixtureFugacityTP::moleFractions_
vector_fp moleFractions_
Storage for the current values of the mole fractions of the species.
Definition: MixtureFugacityTP.h:545
Cantera::MixtureFugacityTP::iState_
int iState_
Current state of the fluid.
Definition: MixtureFugacityTP.h:554
Cantera::MixtureFugacityTP::getCp_R
virtual void getCp_R(doublereal *cpr) const
Get the nondimensional Heat Capacities at constant pressure for the standard state of the species at ...
Definition: MixtureFugacityTP.cpp:113
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::MixtureFugacityTP::phaseState
int phaseState(bool checkState=false) const
Returns the Phase State flag for the current state of the object.
Definition: MixtureFugacityTP.cpp:534
Cantera::MixtureFugacityTP::corr0
int corr0(doublereal TKelvin, doublereal pres, doublereal &densLiq, doublereal &densGas, doublereal &liqGRT, doublereal &gasGRT)
Utility routine in the calculation of the saturation pressure.
Definition: MixtureFugacityTP.cpp:505
Cantera::MixtureFugacityTP::gibbs_RT_ref
const vector_fp & gibbs_RT_ref() const
Returns the vector of nondimensional Gibbs free energies of the reference state at the current temper...
Definition: MixtureFugacityTP.cpp:147
Cantera::Phase::m_kk
size_t m_kk
Number of species in the phase.
Definition: Phase.h:942
Cantera::MixtureFugacityTP::getStandardVolumes
virtual void getStandardVolumes(doublereal *vol) const
Get the molar volumes of each species in their standard states at the current T and P of the solution...
Definition: MixtureFugacityTP.cpp:119
Cantera::MixtureFugacityTP::getGibbs_RT
virtual void getGibbs_RT(doublereal *grt) const
Get the nondimensional Gibbs functions for the species at their standard states of solution at the cu...
Definition: MixtureFugacityTP.cpp:84
Cantera::MixtureFugacityTP::getStandardVolumes_ref
virtual void getStandardVolumes_ref(doublereal *vol) const
Get the molar volumes of the species reference states at the current T and P_ref of the solution.
Definition: MixtureFugacityTP.cpp:165
MixtureFugacityTP.h
Cantera::MixtureFugacityTP::getEnthalpy_RT
virtual void getEnthalpy_RT(doublereal *hrt) const
Get the nondimensional Enthalpy functions for the species at their standard states at the current T a...
Definition: MixtureFugacityTP.cpp:69
Cantera::MixtureFugacityTP::setState_TP
virtual void setState_TP(doublereal T, doublereal pres)
Set the temperature (K) and pressure (Pa)
Definition: MixtureFugacityTP.cpp:252
Cantera::ThermoPhase::addSpecies
virtual bool addSpecies(shared_ptr< Species > spec)
Definition: ThermoPhase.cpp:1134
Cantera::Phase::density
virtual double density() const
Density (kg/m^3).
Definition: Phase.h:685
Cantera::MixtureFugacityTP::getEntropy_R
virtual void getEntropy_R(doublereal *sr) const
Get the array of nondimensional Enthalpy functions for the standard state species at the current T an...
Definition: MixtureFugacityTP.cpp:74
Cantera::MixtureFugacityTP::m_cp0_R
vector_fp m_cp0_R
Temporary storage for dimensionless reference state heat capacities.
Definition: MixtureFugacityTP.h:567
Cantera::MixtureFugacityTP::liquidVolEst
virtual doublereal liquidVolEst(doublereal TKelvin, doublereal &pres) const
Estimate for the molar volume of the liquid.
Definition: MixtureFugacityTP.cpp:360
Cantera::MixtureFugacityTP::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: MixtureFugacityTP.cpp:173
Cantera::MixtureFugacityTP::satPressure
virtual doublereal satPressure(doublereal TKelvin)
Calculate the saturation pressure at the current mixture content for the given temperature.
Definition: MixtureFugacityTP.cpp:585
Cantera::MixtureFugacityTP::calcDensity
virtual void calcDensity()
Calculate the density of the mixture using the partial molar volumes and mole fractions as input.
Definition: MixtureFugacityTP.cpp:247
Cantera::MixtureFugacityTP::getIntEnergy_RT
virtual void getIntEnergy_RT(doublereal *urt) const
Returns the vector of nondimensional internal Energies of the standard state at the current temperatu...
Definition: MixtureFugacityTP.cpp:104
Cantera::MixtureFugacityTP::getEnthalpy_RT_ref
virtual void getEnthalpy_RT_ref(doublereal *hrt) const
Definition: MixtureFugacityTP.cpp:129
Cantera::MixtureFugacityTP::m_h0_RT
vector_fp m_h0_RT
Temporary storage for dimensionless reference state enthalpies.
Definition: MixtureFugacityTP.h:564
Cantera::ThermoPhase::critDensity
virtual doublereal critDensity() const
Critical density (kg/m3).
Definition: ThermoPhase.h:1501
Cantera::MixtureFugacityTP::forcedSolutionBranch
virtual int forcedSolutionBranch() const
Report the solution branch which the solution is restricted to.
Definition: MixtureFugacityTP.cpp:37
Cantera::XML_Node
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:103
Cantera::MixtureFugacityTP::setState_TPX
virtual void setState_TPX(doublereal t, doublereal p, const doublereal *x)
Set the temperature (K), pressure (Pa), and mole fractions.
Definition: MixtureFugacityTP.cpp:328
Cantera::MixtureFugacityTP::hresid
virtual doublereal hresid() const
Calculate the deviation terms for the total enthalpy of the mixture from the ideal gas mixture.
Definition: MixtureFugacityTP.cpp:344
Cantera::ThermoPhase::RT
doublereal RT() const
Return the Gas Constant multiplied by the current temperature.
Definition: ThermoPhase.h:776
Cantera::MixtureFugacityTP::sresid
virtual doublereal sresid() const
Calculate the deviation terms for the total entropy of the mixture from the ideal gas mixture.
Definition: MixtureFugacityTP.cpp:339
Cantera::MixtureFugacityTP::dpdVCalc
virtual doublereal dpdVCalc(doublereal TKelvin, doublereal molarVol, doublereal &presCalc) const
Calculate the pressure and the pressure derivative given the temperature and the molar volume.
Definition: MixtureFugacityTP.cpp:787
Cantera::MixtureFugacityTP::standardStateConvention
virtual int standardStateConvention() const
This method returns the convention used in specification of the standard state, of which there are cu...
Definition: MixtureFugacityTP.cpp:27
Cantera::MixtureFugacityTP::densityCalc
virtual doublereal densityCalc(doublereal TKelvin, doublereal pressure, int phaseRequested, doublereal rhoguess)
Calculates the density given the temperature and the pressure and a guess at the density.
Definition: MixtureFugacityTP.cpp:365
Cantera::Phase::setMoleFractions
virtual void setMoleFractions(const double *const x)
Set the mole fractions to the specified values.
Definition: Phase.cpp:368
Cantera::MixtureFugacityTP::z
doublereal z() const
Calculate the value of z.
Definition: MixtureFugacityTP.cpp:334
Cantera::MixtureFugacityTP::forcedState_
int forcedState_
Force the system to be on a particular side of the spinodal curve.
Definition: MixtureFugacityTP.h:557
Cantera::MixtureFugacityTP::getGibbs_RT_ref
virtual void getGibbs_RT_ref(doublereal *grt) const
Returns the vector of nondimensional Gibbs Free Energies of the reference state at the current temper...
Definition: MixtureFugacityTP.cpp:135
ctml.h
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
stringUtils.h
Cantera::Phase::pressure
virtual double pressure() const
Return the thermodynamic pressure (Pa).
Definition: Phase.h:679
Cantera::MixtureFugacityTP::getChemPotentials_RT
virtual void getChemPotentials_RT(doublereal *mu) const
Get the array of non-dimensional species chemical potentials These are partial molar Gibbs free energ...
Definition: MixtureFugacityTP.cpp:49
Cantera::Phase::temperature
doublereal temperature() const
Temperature (K).
Definition: Phase.h:667
Cantera::MixtureFugacityTP::psatEst
virtual doublereal psatEst(doublereal TKelvin) const
Estimate for the saturation pressure.
Definition: MixtureFugacityTP.cpp:349
Cantera::ThermoPhase::critPressure
virtual doublereal critPressure() const
Critical pressure (Pa).
Definition: ThermoPhase.h:1486
Cantera::MixtureFugacityTP::calculatePsat
doublereal calculatePsat(doublereal TKelvin, doublereal &molarVolGas, doublereal &molarVolLiquid)
Calculate the saturation pressure at the current mixture content for the given temperature.
Definition: MixtureFugacityTP.cpp:592
Cantera::scale
void scale(InputIter begin, InputIter end, OutputIter out, S scale_factor)
Multiply elements of an array by a scale factor.
Definition: utilities.h:135
Cantera::ThermoPhase::m_spthermo
MultiSpeciesThermo m_spthermo
Pointer to the calculation manager for species reference-state thermodynamic properties.
Definition: ThermoPhase.h:1870
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::MixtureFugacityTP::m_g0_RT
vector_fp m_g0_RT
Temporary storage for dimensionless reference state Gibbs energies.
Definition: MixtureFugacityTP.h:570
Cantera::ThermoPhase::gibbs_mole
virtual doublereal gibbs_mole() const
Molar Gibbs function. Units: J/kmol.
Definition: ThermoPhase.h:249
Cantera::MixtureFugacityTP::reportSolnBranchActual
virtual int reportSolnBranchActual() const
Report the solution branch which the solution is actually on.
Definition: MixtureFugacityTP.cpp:42
Cantera::MixtureFugacityTP::invalidateCache
virtual void invalidateCache()
Invalidate any cached values which are normally updated only when a change in state is detected.
Definition: MixtureFugacityTP.cpp:813
Cantera::ThermoPhase::getChemPotentials
virtual void getChemPotentials(doublereal *mu) const
Get the species chemical potentials. Units: J/kmol.
Definition: ThermoPhase.h:489
Cantera::warn_user
void warn_user(const std::string &method, const std::string &msg, const Args &... args)
Definition: global.h:206
Cantera::GasConstant
const double GasConstant
Universal Gas Constant [J/kmol/K].
Definition: ct_defs.h:109
Cantera::CanteraError
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:60
Cantera::MixtureFugacityTP::setTemperature
virtual void setTemperature(const doublereal temp)
Set the temperature of the phase.
Definition: MixtureFugacityTP.cpp:223
Cantera::MixtureFugacityTP::getPureGibbs
virtual void getPureGibbs(doublereal *gpure) const
Get the pure Gibbs free energies of each species.
Definition: MixtureFugacityTP.cpp:94
Cantera::MixtureFugacityTP::addSpecies
virtual bool addSpecies(shared_ptr< Species > spec)
Definition: MixtureFugacityTP.cpp:206
Cantera::MixtureFugacityTP::m_s0_R
vector_fp m_s0_R
Temporary storage for dimensionless reference state entropies.
Definition: MixtureFugacityTP.h:573
Cantera::MixtureFugacityTP::getGibbs_ref
virtual void getGibbs_ref(doublereal *g) const
Returns the vector of the Gibbs function of the reference state at the current temperature of the sol...
Definition: MixtureFugacityTP.cpp:141
Cantera
Namespace for the Cantera kernel.
Definition: AnyMap.cpp:263
Cantera::MixtureFugacityTP::_updateReferenceStateThermo
virtual void _updateReferenceStateThermo() const
Updates the reference state thermodynamic functions at the current T of the solution.
Definition: MixtureFugacityTP.cpp:792
Cantera::Phase::compositionChanged
virtual void compositionChanged()
Apply changes to the state which are needed after the composition changes.
Definition: Phase.cpp:1028
Cantera::MixtureFugacityTP::densSpinodalLiquid
virtual doublereal densSpinodalLiquid() const
Return the value of the density at the liquid spinodal point (on the liquid side) for the current tem...
Definition: MixtureFugacityTP.cpp:575
Cantera::ThermoPhase::critTemperature
virtual doublereal critTemperature() const
Critical temperature (K).
Definition: ThermoPhase.h:1481
Cantera::Phase::setMoleFractionsByName
void setMoleFractionsByName(const compositionMap &xMap)
Set the species mole fractions by name.
Definition: Phase.cpp:409