27 MixtureFugacityTP::MixtureFugacityTP() :
32 forcedState_(FLUID_UNDEFINED),
56 forcedState_(FLUID_UNDEFINED),
195 throw CanteraError(
"MixtureFugacityTP",
"Base class method "
216 doublereal invRT = 1.0 /
_RT();
217 for (
size_t k = 0; k <
m_kk; k++) {
229 doublereal RT =
_RT();
231 for (
size_t k = 0; k <
m_kk; k++) {
232 g[k] = RT * (g[k] + tmp);
241 #ifdef H298MODIFY_CAPABILITY
267 for (
size_t k = 0; k <
m_kk; k++) {
281 for (
size_t k = 0; k <
m_kk; k++) {
297 for (
size_t k = 0; k <
m_kk; k++) {
312 doublereal tmp = p /
_RT();
313 doublereal v0 =
_RT() / p;
314 for (
size_t i = 0; i <
m_kk; i++) {
342 for (
size_t i = 0; i <
m_kk; i++) {
385 scale(gibbsrt.begin(), gibbsrt.end(), g,
_RT());
428 doublereal v0 =
_RT() / pp;
429 for (
size_t i = 0; i <
m_kk; i++) {
461 if (state.
hasChild(
"temperature")) {
468 }
else if (state.
hasChild(
"density")) {
549 void MixtureFugacityTP::setMoleFractions_NoState(
const doublereal*
const x)
553 updateMixingExpressions();
558 err(
"MixtureFugacityTP::calcDensity() called, but EOS for phase is not known");
579 updateMixingExpressions();
593 rho =
densityCalc(t, pres, FLUID_UNDEFINED , rhoNow);
599 throw CanteraError(
"MixtureFugacityTP::setState_TP()",
"neg rho");
602 throw CanteraError(
"MixtureFugacityTP::setState_TP()",
"neg rho");
610 if (
iState_ < FLUID_LIQUID_0) {
617 if (
iState_ >= FLUID_LIQUID_0) {
618 throw CanteraError(
"MixtureFugacityTP::setState_TP()",
"wrong state");
621 throw CanteraError(
"MixtureFugacityTP::setState_TP()",
"neg rho");
628 if (
iState_ >= FLUID_LIQUID_0) {
636 throw CanteraError(
"MixtureFugacityTP::setState_TP()",
"wrong state");
639 throw CanteraError(
"MixtureFugacityTP::setState_TP()",
"neg rho");
668 updateMixingExpressions();
689 setMoleFractions_NoState(x);
725 doublereal molarV = mmw / rho;
726 doublereal rt =
_RT();
727 doublereal zz = p * molarV / rt;
733 throw CanteraError(
"MixtureFugacityTP::sresid()",
"Base Class: not implemented");
739 throw CanteraError(
"MixtureFugacityTP::hresid()",
"Base Class: not implemented");
747 doublereal tt = tcrit/TKelvin;
751 doublereal lpr = -0.8734*tt*tt - 3.4522*tt + 4.2918;
752 return pcrit*exp(lpr);
757 throw CanteraError(
"MixtureFugacityTP::liquidVolEst()",
"unimplemented");
781 int phase, doublereal rhoguess)
787 if (rhoguess == -1.0) {
789 if (TKelvin > tcrit) {
792 if (phase == FLUID_GAS || phase == FLUID_SUPERCRIT) {
794 }
else if (phase >= FLUID_LIQUID_0) {
796 rhoguess = mmw / lqvol;
809 double molarVolBase = mmw / rhoguess;
810 double molarVolLast = molarVolBase;
816 double molarVolSpinodal = vc;
817 doublereal pcheck = 1.0E-30 + 1.0E-8 * presPa;
818 doublereal presBase, dpdVBase, delMV;
823 bool gasSide = molarVolBase > vc;
834 for (
int n = 0; n < 200; n++) {
846 dpdVBase =
dpdVCalc(TKelvin, molarVolBase, presBase);
853 if (dpdVBase >= 0.0) {
854 if (TKelvin > tcrit) {
863 if (molarVolBase >= vc) {
864 molarVolSpinodal = molarVolBase;
865 molarVolBase = 0.5 * (molarVolLast + molarVolSpinodal);
867 molarVolBase = 0.5 * (molarVolLast + molarVolSpinodal);
870 if (molarVolBase <= vc) {
871 molarVolSpinodal = molarVolBase;
872 molarVolBase = 0.5 * (molarVolLast + molarVolSpinodal);
874 molarVolBase = 0.5 * (molarVolLast + molarVolSpinodal);
883 if (fabs(presBase-presPa) < pcheck) {
891 doublereal dpdV = dpdVBase;
893 dpdV = dpdVBase * 1.5;
902 delMV = - (presBase - presPa) / dpdV;
903 if (!gasSide || delMV < 0.0) {
904 if (fabs(delMV) > 0.2 * molarVolBase) {
905 delMV = delMV / fabs(delMV) * 0.2 * molarVolBase;
911 if (TKelvin < tcrit) {
914 if (-delMV > 0.5 * (molarVolBase - molarVolSpinodal)) {
915 delMV = - 0.5 * (molarVolBase - molarVolSpinodal);
920 if (delMV > 0.5 * (molarVolSpinodal - molarVolBase)) {
921 delMV = 0.5 * (molarVolSpinodal - molarVolBase);
929 molarVolLast = molarVolBase;
930 molarVolBase += delMV;
933 if (fabs(delMV/molarVolBase) < 1.0E-14) {
941 if (molarVolBase <= 0.0) {
942 molarVolBase =
std::min(1.0E-30, fabs(delMV*1.0E-4));
951 double densBase = 0.0;
954 throw CanteraError(
"MixtureFugacityTP::densityCalc()",
"Process didnot converge");
956 densBase = mmw / molarVolBase;
961 void MixtureFugacityTP::updateMixingExpressions()
966 MixtureFugacityTP::spinodalFunc::spinodalFunc(MixtureFugacityTP* tp) :
972 int MixtureFugacityTP::spinodalFunc::evalSS(
const doublereal t,
const doublereal*
const y,
976 doublereal molarVol = y[0];
977 doublereal tt = m_tp->temperature();
979 doublereal val = m_tp->dpdVCalc(tt, molarVol, pp);
986 doublereal& densGasGuess, doublereal& liqGRT, doublereal& gasGRT)
990 doublereal densLiq =
densityCalc(TKelvin, pres, FLUID_LIQUID_0, densLiqGuess);
991 if (densLiq <= 0.0) {
997 densLiqGuess = densLiq;
1002 doublereal densGas =
densityCalc(TKelvin, pres, FLUID_GAS, densGasGuess);
1003 if (densGas <= 0.0) {
1009 "Error occurred trying to find gas density at (T,P) = "
1014 densGasGuess = densGas;
1040 state = FLUID_SUPERCRIT;
1043 double tmid = tcrit - 100.;
1051 double densLiqTmid = mmw / molVolLiqTmid;
1052 double densGasTmid = mmw / molVolGasTmid;
1053 double densMidTmid = 0.5 * (densLiqTmid + densGasTmid);
1054 doublereal rhoMid = rhocrit + (t - tcrit) * (rhocrit - densMidTmid) / (tcrit - tmid);
1057 int iStateGuess = FLUID_LIQUID_0;
1059 iStateGuess = FLUID_GAS;
1061 double molarVol = mmw / rho;
1064 double dpdv =
dpdVCalc(t, molarVol, presCalc);
1066 state = iStateGuess;
1128 doublereal& molarVolLiquid)
1133 double RhoLiquid, RhoGas;
1134 double RhoLiquidGood, RhoGasGood;
1139 if (TKelvin < tcrit) {
1145 RhoLiquidGood = mw / volLiquid;
1147 doublereal delGRT = 1.0E6;
1148 doublereal liqGRT, gasGRT;
1150 doublereal presLast = pres;
1156 doublereal presLiquid;
1158 doublereal presBase = pres;
1159 bool foundLiquid =
false;
1160 bool foundGas =
false;
1162 doublereal densLiquid =
densityCalc(TKelvin, presBase, FLUID_LIQUID_0, RhoLiquidGood);
1163 if (densLiquid > 0.0) {
1166 RhoLiquidGood = densLiquid;
1169 for (
int i = 0; i < 50; i++) {
1171 densLiquid =
densityCalc(TKelvin, pres, FLUID_LIQUID_0, RhoLiquidGood);
1172 if (densLiquid > 0.0) {
1175 RhoLiquidGood = densLiquid;
1182 doublereal densGas =
densityCalc(TKelvin, pres, FLUID_GAS, RhoGasGood);
1183 if (densGas <= 0.0) {
1188 RhoGasGood = densGas;
1191 for (
int i = 0; i < 50; i++) {
1193 densGas =
densityCalc(TKelvin, pres, FLUID_GAS, RhoGasGood);
1194 if (densGas > 0.0) {
1197 RhoGasGood = densGas;
1203 if (foundGas && foundLiquid) {
1204 if (presGas == presLiquid) {
1206 goto startIteration;
1208 pres = 0.5 * (presLiquid + presGas);
1211 for (
int i = 0; i < 50; i++) {
1213 doublereal densLiquid =
densityCalc(TKelvin, pres, FLUID_LIQUID_0, RhoLiquidGood);
1214 if (densLiquid <= 0.0) {
1218 RhoLiquidGood = densLiquid;
1221 doublereal densGas =
densityCalc(TKelvin, pres, FLUID_GAS, RhoGasGood);
1222 if (densGas <= 0.0) {
1226 RhoGasGood = densGas;
1229 if (goodGas && goodLiq) {
1232 if (!goodLiq && !goodGas) {
1233 pres = 0.5 * (pres + presLiquid);
1235 if (goodLiq || goodGas) {
1236 pres = 0.5 * (presLiquid + presGas);
1241 if (!foundGas || !foundLiquid) {
1242 printf(
"error coundn't find a starting pressure\n");
1245 if (presGas != presLiquid) {
1246 printf(
"error coundn't find a starting pressure\n");
1253 RhoGas = RhoGasGood;
1254 RhoLiquid = RhoLiquidGood;
1261 for (i = 0; i < 20; i++) {
1263 stab =
corr0(TKelvin, pres, RhoLiquid, RhoGas, liqGRT, gasGRT);
1266 delGRT = liqGRT - gasGRT;
1267 doublereal delV = mw * (1.0/RhoLiquid - 1.0/RhoGas);
1268 doublereal dp = - delGRT *
GasConstant * TKelvin / delV;
1270 if (fabs(dp) > 0.1 * pres) {
1279 }
else if (stab == -1) {
1281 if (presLast > pres) {
1282 pres = 0.5 * (presLast + pres);
1287 }
else if (stab == -2) {
1288 if (presLast < pres) {
1289 pres = 0.5 * (presLast + pres);
1295 molarVolGas = mw / RhoGas;
1296 molarVolLiquid = mw / RhoLiquid;
1299 if (fabs(delGRT) < 1.0E-8) {
1305 molarVolGas = mw / RhoGas;
1306 molarVolLiquid = mw / RhoLiquid;
1317 molarVolGas = mw / RhoGas;
1318 molarVolLiquid = molarVolGas;
1328 throw CanteraError(
"MixtureFugacityTP::pressureCalc",
"unimplemented");
1335 throw CanteraError(
"MixtureFugacityTP::dpdVCalc",
"unimplemented");
1365 for (
size_t k = 0; k <
m_kk; k++) {
1370 throw CanteraError(
"MixtureFugacityTP::_updateReferenceStateThermo()",
"neg ref pressure");