void WaterPropsIAPWS:: corr1(doublereal temperature, doublereal pressure, doublereal &densLiq, doublereal &densGas, doublereal &pcorr) { densLiq = density(temperature, pressure, WATER_LIQUID, densLiq); if (densLiq <= 0.0) { throw Cantera::CanteraError("WaterPropsIAPWS::corr1", "Error occurred trying to find liquid density at (T,P) = " + Cantera::fp2str(temperature) + " " + Cantera::fp2str(pressure)); } setState_TR(temperature, densLiq); doublereal prL = m_phi->phiR(); densGas = density(temperature, pressure, WATER_GAS, densGas); if (densGas <= 0.0) { throw Cantera::CanteraError("WaterPropsIAPWS::corr1", "Error occurred trying to find gas density at (T,P) = " + Cantera::fp2str(temperature) + " " + Cantera::fp2str(pressure)); } setState_TR(temperature, densGas); doublereal prG = m_phi->phiR(); doublereal rhs = (prL - prG) + log(densLiq/densGas); rhs /= (1.0/densGas - 1.0/densLiq); pcorr = rhs * Rgas * temperature / M_water; }
int MixtureFugacityTP::corr0(doublereal TKelvin, doublereal pres, doublereal& densLiqGuess, doublereal& densGasGuess, doublereal& liqGRT, doublereal& gasGRT) { int retn = 0; doublereal densLiq = densityCalc(TKelvin, pres, FLUID_LIQUID_0, densLiqGuess); if (densLiq <= 0.0) { retn = -1; } else { densLiqGuess = densLiq; setState_TR(TKelvin, densLiq); liqGRT = gibbs_mole() / _RT(); } doublereal densGas = densityCalc(TKelvin, pres, FLUID_GAS, densGasGuess); if (densGas <= 0.0) { if (retn == -1) { throw Cantera::CanteraError("MixtureFugacityTP::corr0", "Error occurred trying to find gas density at (T,P) = " + Cantera::fp2str(TKelvin) + " " + Cantera::fp2str(pres)); } retn = -2; } else { densGasGuess = densGas; setState_TR(TKelvin, densGas); gasGRT = gibbs_mole() / _RT(); } return retn; }
void MixtureFugacityTP::setStateFromXML(const XML_Node& state) { int doTP = 0; string comp = ctml::getChildValue(state,"moleFractions"); if (comp != "") { // not overloaded in current object -> phase state is not calculated. setMoleFractionsByName(comp); doTP = 1; } else { comp = ctml::getChildValue(state,"massFractions"); if (comp != "") { // not overloaded in current object -> phase state is not calculated. setMassFractionsByName(comp); doTP = 1; } } double t = temperature(); if (state.hasChild("temperature")) { t = ctml::getFloat(state, "temperature", "temperature"); doTP = 1; } if (state.hasChild("pressure")) { double p = ctml::getFloat(state, "pressure", "pressure"); setState_TP(t, p); } else if (state.hasChild("density")) { double rho = ctml::getFloat(state, "density", "density"); setState_TR(t, rho); } else if (doTP) { double rho = Phase::density(); setState_TR(t, rho); } }
/* * Calculates the density given the temperature and the pressure, * and a guess at the density. Note, below T_c, this is a * multivalued function. * * parameters: * temperature: Kelvin * pressure : Pressure in Pascals (Newton/m**2) * phase : guessed phase of water * : -1: no guessed phase * rhoguess : guessed density of the water * : -1.0 no guessed density * * If a problem is encountered, a negative 1 is returned. */ doublereal WaterPropsIAPWS::density(doublereal temperature, doublereal pressure, int phase, doublereal rhoguess) { doublereal deltaGuess = 0.0; if (rhoguess == -1.0) { if (phase != -1) { if (temperature > T_c) { rhoguess = pressure * M_water / (Rgas * temperature); } else { if (phase == WATER_GAS || phase == WATER_SUPERCRIT) { rhoguess = pressure * M_water / (Rgas * temperature); } else if (phase == WATER_LIQUID) { /* * Provide a guess about the liquid density that is * relatively high -> convergnce from above seems robust. */ rhoguess = 1000.; } else if (phase == WATER_UNSTABLELIQUID || phase == WATER_UNSTABLEGAS) { throw Cantera::CanteraError("WaterPropsIAPWS::density", "Unstable Branch finder is untested"); } else { throw Cantera::CanteraError("WaterPropsIAPWS::density", "unknown state: " + Cantera::int2str(phase)); } } } else { /* * Assume the Gas phase initial guess, if nothing is * specified to the routine */ rhoguess = pressure * M_water / (Rgas * temperature); } } doublereal p_red = pressure * M_water / (Rgas * temperature * Rho_c); deltaGuess = rhoguess / Rho_c; setState_TR(temperature, rhoguess); doublereal delta_retn = m_phi->dfind(p_red, tau, deltaGuess); doublereal density_retn; if (delta_retn >0.0) { delta = delta_retn; /* * Dimensionalize the density before returning */ density_retn = delta_retn * Rho_c; /* * Set the internal state -> this may be * a duplication. However, let's just be sure. */ setState_TR(temperature, density_retn); } else { density_retn = -1.0; } return density_retn; }
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; }
void WaterPropsIAPWS::corr(doublereal temperature, doublereal pressure, doublereal& densLiq, doublereal& densGas, doublereal& delGRT) { densLiq = density(temperature, pressure, WATER_LIQUID, densLiq); if (densLiq <= 0.0) { throw CanteraError("WaterPropsIAPWS::corr", "Error occurred trying to find liquid density at (T,P) = {} {}", temperature, pressure); } setState_TR(temperature, densLiq); doublereal gibbsLiqRT = m_phi.gibbs_RT(); densGas = density(temperature, pressure, WATER_GAS, densGas); if (densGas <= 0.0) { throw CanteraError("WaterPropsIAPWS::corr", "Error occurred trying to find gas density at (T,P) = {} {}", temperature, pressure); } setState_TR(temperature, densGas); doublereal gibbsGasRT = m_phi.gibbs_RT(); delGRT = gibbsLiqRT - gibbsGasRT; }
doublereal MixtureFugacityTP::calculatePsat(doublereal TKelvin, doublereal& molarVolGas, doublereal& molarVolLiquid) { /* * The algorithm for this routine has undergone quite a bit of work. It probably needs more work. * However, it seems now to be fairly robust. * The key requirement is to find an initial pressure where both the liquid and the gas exist. This * is not as easy as it sounds, and it gets exceedingly hard as the critical temperature is approached * from below. * Once we have this initial state, then we seek to equilibrate the gibbs free energies of the * gas and liquid and use the formula * * dp = VdG * * to create an update condition for deltaP using * * - (Gliq - Ggas) = (Vliq - Vgas) (deltaP) * * @TODO Suggestions for the future would be to switch it to an algorithm that uses the gas molar volume * and the liquid molar volumes as the fundamental unknowns. */ // we need this because this is a non-const routine that is public setTemperature(TKelvin); double densSave = density(); double tempSave = temperature(); double pres; doublereal mw = meanMolecularWeight(); if (TKelvin < critTemperature()) { pres = psatEst(TKelvin); // trial value = Psat from correlation doublereal volLiquid = liquidVolEst(TKelvin, pres); double RhoLiquidGood = mw / volLiquid; double RhoGasGood = pres * mw / (GasConstant * TKelvin); doublereal delGRT = 1.0E6; doublereal liqGRT, gasGRT; /* * First part of the calculation involves finding a pressure at which the * gas and the liquid state coexists. */ doublereal presLiquid = 0.; doublereal presGas; doublereal presBase = pres; bool foundLiquid = false; bool foundGas = false; doublereal densLiquid = densityCalc(TKelvin, presBase, FLUID_LIQUID_0, RhoLiquidGood); if (densLiquid > 0.0) { foundLiquid = true; presLiquid = pres; RhoLiquidGood = densLiquid; } if (!foundLiquid) { for (int i = 0; i < 50; i++) { pres = 1.1 * pres; densLiquid = densityCalc(TKelvin, pres, FLUID_LIQUID_0, RhoLiquidGood); if (densLiquid > 0.0) { foundLiquid = true; presLiquid = pres; RhoLiquidGood = densLiquid; break; } } } pres = presBase; doublereal densGas = densityCalc(TKelvin, pres, FLUID_GAS, RhoGasGood); if (densGas <= 0.0) { foundGas = false; } else { foundGas = true; presGas = pres; RhoGasGood = densGas; } if (!foundGas) { for (int i = 0; i < 50; i++) { pres = 0.9 * pres; densGas = densityCalc(TKelvin, pres, FLUID_GAS, RhoGasGood); if (densGas > 0.0) { foundGas = true; presGas = pres; RhoGasGood = densGas; break; } } } if (foundGas && foundLiquid) { if (presGas != presLiquid) { pres = 0.5 * (presLiquid + presGas); bool goodLiq; bool goodGas; for (int i = 0; i < 50; i++) { densLiquid = densityCalc(TKelvin, pres, FLUID_LIQUID_0, RhoLiquidGood); if (densLiquid <= 0.0) { goodLiq = false; } else { goodLiq = true; RhoLiquidGood = densLiquid; presLiquid = pres; } densGas = densityCalc(TKelvin, pres, FLUID_GAS, RhoGasGood); if (densGas <= 0.0) { goodGas = false; } else { goodGas = true; RhoGasGood = densGas; presGas = pres; } if (goodGas && goodLiq) { break; } if (!goodLiq && !goodGas) { pres = 0.5 * (pres + presLiquid); } if (goodLiq || goodGas) { pres = 0.5 * (presLiquid + presGas); } } } } if (!foundGas || !foundLiquid) { printf("error coundn't find a starting pressure\n"); return 0.0; } if (presGas != presLiquid) { printf("error coundn't find a starting pressure\n"); return 0.0; } pres = presGas; double presLast = pres; double RhoGas = RhoGasGood; double RhoLiquid = RhoLiquidGood; /* * Now that we have found a good pressure we can proceed with the algorithm. */ for (int i = 0; i < 20; i++) { int stab = corr0(TKelvin, pres, RhoLiquid, RhoGas, liqGRT, gasGRT); if (stab == 0) { presLast = pres; delGRT = liqGRT - gasGRT; doublereal delV = mw * (1.0/RhoLiquid - 1.0/RhoGas); doublereal dp = - delGRT * GasConstant * TKelvin / delV; if (fabs(dp) > 0.1 * pres) { if (dp > 0.0) { dp = 0.1 * pres; } else { dp = -0.1 * pres; } } pres += dp; } else if (stab == -1) { delGRT = 1.0E6; if (presLast > pres) { pres = 0.5 * (presLast + pres); } else { // we are stuck here - try this pres = 1.1 * pres; } } else if (stab == -2) { if (presLast < pres) { pres = 0.5 * (presLast + pres); } else { // we are stuck here - try this pres = 0.9 * pres; } } molarVolGas = mw / RhoGas; molarVolLiquid = mw / RhoLiquid; if (fabs(delGRT) < 1.0E-8) { // converged break; } } molarVolGas = mw / RhoGas; molarVolLiquid = mw / RhoLiquid; // Put the fluid in the desired end condition setState_TR(tempSave, densSave); return pres; } else { pres = critPressure(); setState_TP(TKelvin, pres); molarVolGas = mw / density(); molarVolLiquid = molarVolGas; setState_TR(tempSave, densSave); } return pres; }
void MixtureFugacityTP::setTemperature(const doublereal temp) { _updateReferenceStateThermo(); setState_TR(temperature(), density()); }