doublereal WaterPropsIAPWS::psat(doublereal temperature, int waterState) { doublereal densLiq = -1.0, densGas = -1.0, delGRT = 0.0; doublereal dp, pcorr; if (temperature >= T_c) { densGas = density(temperature, P_c, WATER_SUPERCRIT); setState_TR(temperature, densGas); return P_c; } doublereal p = psat_est(temperature); bool conv = false; for (int i = 0; i < 30; i++) { if (method == 1) { corr(temperature, p, densLiq, densGas, delGRT); doublereal delV = M_water * (1.0/densLiq - 1.0/densGas); dp = - delGRT * Rgas * temperature / delV; } else { corr1(temperature, p, densLiq, densGas, pcorr); dp = pcorr - p; } p += dp; if ((method == 1) && delGRT < 1.0E-8) { conv = true; break; } else { if (fabs(dp/p) < 1.0E-9) { conv = true; break; } } } // Put the fluid in the desired end condition if (waterState == WATER_LIQUID) { setState_TR(temperature, densLiq); } else if (waterState == WATER_GAS) { setState_TR(temperature, densGas); } else { throw Cantera::CanteraError("WaterPropsIAPWS::psat", "unknown water state input: " + Cantera::int2str(waterState)); } return p; }
doublereal WaterPropsIAPWS::densSpinodalSteam() const { doublereal temperature = T_c/tau; doublereal delta_save = delta; // return the critical density if we are above or even just a little below // the critical temperature. We just don't want to worry about the critical // point at this juncture. if (temperature >= T_c - 0.001) { return Rho_c; } doublereal p = psat_est(temperature); doublereal rho_low = 0.0; doublereal rho_high = 1000; doublereal densSatGas = density_const(p, WATER_GAS); doublereal dens_old = densSatGas; delta = dens_old / Rho_c; m_phi.tdpolycalc(tau, delta); doublereal dpdrho_old = dpdrho(); if (dpdrho_old < 0.0) { rho_high = std::min(dens_old, rho_high); } else { rho_low = std::max(rho_low, dens_old); } doublereal dens_new = densSatGas * (0.99); delta = dens_new / Rho_c; m_phi.tdpolycalc(tau, delta); doublereal dpdrho_new = dpdrho(); if (dpdrho_new < 0.0) { rho_high = std::min(dens_new, rho_high); } else { rho_low = std::max(rho_low, dens_new); } bool conv = false; for (int it = 0; it < 50; it++) { doublereal slope = (dpdrho_new - dpdrho_old)/(dens_new - dens_old); if (slope >= 0.0) { slope = dpdrho_new; // shouldn't be here for gas spinodal } else { slope = std::min(slope, dpdrho_new *5.0 / dens_new); } doublereal delta_rho = - dpdrho_new / slope; if (delta_rho > 0.0) { delta_rho = std::min(delta_rho, dens_new * 0.1); } else { delta_rho = std::max(delta_rho, - dens_new * 0.1); } doublereal dens_est = dens_new + delta_rho; if (dens_est < rho_low) { dens_est = 0.5 * (rho_low + dens_new); } if (dens_est > rho_high) { dens_est = 0.5 * (rho_high + dens_new); } dens_old = dens_new; dpdrho_old = dpdrho_new; dens_new = dens_est; delta = dens_new / Rho_c; m_phi.tdpolycalc(tau, delta); dpdrho_new = dpdrho(); if (dpdrho_new < 0.0) { rho_high = std::min(dens_new, rho_high); } else if (dpdrho_new > 0.0) { rho_low = std::max(rho_low, dens_new); } else { conv = true; break; } if (fabs(dpdrho_new) < 1.0E-5) { conv = true; break; } } if (!conv) { throw CanteraError("WaterPropsIAPWS::densSpinodalSteam()", "convergence failure"); } // Restore the original delta delta = delta_save; m_phi.tdpolycalc(tau, delta); return dens_new; }