void GibbsExcessVPSSTP::calcDensity() { vector_fp vbar = getPartialMolarVolumesVector(); doublereal vtotal = 0.0; for (size_t i = 0; i < m_kk; i++) { vtotal += vbar[i] * moleFractions_[i]; } doublereal dd = meanMolecularWeight() / vtotal; Phase::setDensity(dd); }
std::string MolarityIonicVPSSTP::report(bool show_thermo, doublereal threshold) const { fmt::MemoryWriter b; try { if (name() != "") { b.write("\n {}:\n", name()); } b.write("\n"); b.write(" temperature {:12.6g} K\n", temperature()); b.write(" pressure {:12.6g} Pa\n", pressure()); b.write(" density {:12.6g} kg/m^3\n", density()); b.write(" mean mol. weight {:12.6g} amu\n", meanMolecularWeight()); doublereal phi = electricPotential(); b.write(" potential {:12.6g} V\n", phi); vector_fp x(m_kk); vector_fp molal(m_kk); vector_fp mu(m_kk); vector_fp muss(m_kk); vector_fp acMolal(m_kk); vector_fp actMolal(m_kk); getMoleFractions(&x[0]); getChemPotentials(&mu[0]); getStandardChemPotentials(&muss[0]); getActivities(&actMolal[0]); if (show_thermo) { b.write("\n"); b.write(" 1 kg 1 kmol\n"); b.write(" ----------- ------------\n"); b.write(" enthalpy {:12.6g} {:12.4g} J\n", enthalpy_mass(), enthalpy_mole()); b.write(" internal energy {:12.6g} {:12.4g} J\n", intEnergy_mass(), intEnergy_mole()); b.write(" entropy {:12.6g} {:12.4g} J/K\n", entropy_mass(), entropy_mole()); b.write(" Gibbs function {:12.6g} {:12.4g} J\n", gibbs_mass(), gibbs_mole()); b.write(" heat capacity c_p {:12.6g} {:12.4g} J/K\n", cp_mass(), cp_mole()); try { b.write(" heat capacity c_v {:12.6g} {:12.4g} J/K\n", cv_mass(), cv_mole()); } catch (NotImplementedError& e) { b.write(" heat capacity c_v <not implemented>\n"); } } } catch (CanteraError& e) { return b.str() + e.what(); } return b.str(); }
void MaskellSolidSolnPhase::calcDensity() { const vector_fp& vbar = getStandardVolumes(); vector_fp moleFracs(m_kk); Phase::getMoleFractions(&moleFracs[0]); doublereal vtotal = 0.0; for (size_t i = 0; i < m_kk; i++) { vtotal += vbar[i] * moleFracs[i]; } Phase::setDensity(meanMolecularWeight() / vtotal); }
void GibbsExcessVPSSTP::calcDensity() { doublereal* vbar = NULL; vbar = new doublereal[m_kk]; // double *vbar = &m_pp[0]; getPartialMolarVolumes(vbar); doublereal vtotal = 0.0; for (int i = 0; i < m_kk; i++) { vtotal += vbar[i] * moleFractions_[i]; } doublereal dd = meanMolecularWeight() / vtotal; State::setDensity(dd); delete [] vbar; }
void WaterSSTP::getStandardVolumes_ref(doublereal* vol) const { doublereal p = pressure(); double T = temperature(); double dens = density(); int waterState = WATER_GAS; double rc = m_sub.Rhocrit(); if (dens > rc) { waterState = WATER_LIQUID; } doublereal dd = m_sub.density(T, OneAtm, waterState, dens); if (dd <= 0.0) { throw CanteraError("setPressure", "error"); } *vol = meanMolecularWeight() /dd; dd = m_sub.density(T, p, waterState, dens); }
void IdealSolnGasVPSS::calcDensity() { /* * Calculate the molarVolume of the solution (m**3 kmol-1) */ if (m_idealGas) { double dens = (m_Pcurrent * meanMolecularWeight() /(GasConstant * temperature())); State::setDensity(dens); } else { const doublereal * const dtmp = moleFractdivMMW(); const vector_fp& vss = m_VPSS_ptr->standardVolumes(); double invDens = dot(vss.begin(), vss.end(), dtmp); /* * Set the density in the parent State object directly, * by calling the State::setDensity() function. */ double dens = 1.0/invDens; State::setDensity(dens); } }
int MixtureFugacityTP::phaseState(bool checkState) const { int state = iState_; if (checkState) { double t = temperature(); double tcrit = critTemperature(); double rhocrit = critDensity(); if (t >= tcrit) { return FLUID_SUPERCRIT; } double tmid = tcrit - 100.; if (tmid < 0.0) { tmid = tcrit / 2.0; } double pp = psatEst(tmid); double mmw = meanMolecularWeight(); double molVolLiqTmid = liquidVolEst(tmid, pp); double molVolGasTmid = GasConstant * tmid / (pp); double densLiqTmid = mmw / molVolLiqTmid; double densGasTmid = mmw / molVolGasTmid; double densMidTmid = 0.5 * (densLiqTmid + densGasTmid); doublereal rhoMid = rhocrit + (t - tcrit) * (rhocrit - densMidTmid) / (tcrit - tmid); double rho = density(); int iStateGuess = FLUID_LIQUID_0; if (rho < rhoMid) { iStateGuess = FLUID_GAS; } double molarVol = mmw / rho; double presCalc; double dpdv = dpdVCalc(t, molarVol, presCalc); if (dpdv < 0.0) { state = iStateGuess; } else { state = FLUID_UNSTABLE; } } return state; }
void IdealSolidSolnPhase::getActivityConcentrations(doublereal* c) const { const doublereal* const dtmp = moleFractdivMMW(); const double mmw = meanMolecularWeight(); switch (m_formGC) { case 0: for (size_t k = 0; k < m_kk; k++) { c[k] = dtmp[k] * mmw; } break; case 1: for (size_t k = 0; k < m_kk; k++) { c[k] = dtmp[k] * mmw / m_speciesMolarVolume[k]; } break; case 2: double atmp = mmw / m_speciesMolarVolume[m_kk-1]; for (size_t k = 0; k < m_kk; k++) { c[k] = dtmp[k] * atmp; } break; } }
void IdealMolalSoln::calcDensity() { getPartialMolarVolumes(m_tmpV.data()); doublereal dd = meanMolecularWeight() / mean_X(m_tmpV); Phase::setDensity(dd); }
void Phase::setMolarDensity(const doublereal molar_density) { m_dens = molar_density*meanMolecularWeight(); }
doublereal Phase::molarDensity() const { return density()/meanMolecularWeight(); }
/* * Format a summary of the mixture state for output. */ void MolalityVPSSTP::reportCSV(std::ofstream& csvFile) const { csvFile.precision(3); int tabS = 15; int tabM = 30; int tabL = 40; try { if (name() != "") { csvFile << "\n"+name()+"\n\n"; } csvFile << setw(tabL) << "temperature (K) =" << setw(tabS) << temperature() << endl; csvFile << setw(tabL) << "pressure (Pa) =" << setw(tabS) << pressure() << endl; csvFile << setw(tabL) << "density (kg/m^3) =" << setw(tabS) << density() << endl; csvFile << setw(tabL) << "mean mol. weight (amu) =" << setw(tabS) << meanMolecularWeight() << endl; csvFile << setw(tabL) << "potential (V) =" << setw(tabS) << electricPotential() << endl; csvFile << endl; csvFile << setw(tabL) << "enthalpy (J/kg) = " << setw(tabS) << enthalpy_mass() << setw(tabL) << "enthalpy (J/kmol) = " << setw(tabS) << enthalpy_mole() << endl; csvFile << setw(tabL) << "internal E (J/kg) = " << setw(tabS) << intEnergy_mass() << setw(tabL) << "internal E (J/kmol) = " << setw(tabS) << intEnergy_mole() << endl; csvFile << setw(tabL) << "entropy (J/kg) = " << setw(tabS) << entropy_mass() << setw(tabL) << "entropy (J/kmol) = " << setw(tabS) << entropy_mole() << endl; csvFile << setw(tabL) << "Gibbs (J/kg) = " << setw(tabS) << gibbs_mass() << setw(tabL) << "Gibbs (J/kmol) = " << setw(tabS) << gibbs_mole() << endl; csvFile << setw(tabL) << "heat capacity c_p (J/K/kg) = " << setw(tabS) << cp_mass() << setw(tabL) << "heat capacity c_p (J/K/kmol) = " << setw(tabS) << cp_mole() << endl; csvFile << setw(tabL) << "heat capacity c_v (J/K/kg) = " << setw(tabS) << cv_mass() << setw(tabL) << "heat capacity c_v (J/K/kmol) = " << setw(tabS) << cv_mole() << endl; csvFile.precision(8); vector<std::string> pNames; vector<vector_fp> data; vector_fp temp(nSpecies()); getMoleFractions(&temp[0]); pNames.push_back("X"); data.push_back(temp); try { getMolalities(&temp[0]); pNames.push_back("Molal"); data.push_back(temp); } catch (CanteraError& err) { err.save(); } try { getChemPotentials(&temp[0]); pNames.push_back("Chem. Pot. (J/kmol)"); data.push_back(temp); } catch (CanteraError& err) { err.save(); } try { getStandardChemPotentials(&temp[0]); pNames.push_back("Chem. Pot. SS (J/kmol)"); data.push_back(temp); } catch (CanteraError& err) { err.save(); } try { getMolalityActivityCoefficients(&temp[0]); pNames.push_back("Molal Act. Coeff."); data.push_back(temp); } catch (CanteraError& err) { err.save(); } try { getActivities(&temp[0]); pNames.push_back("Molal Activity"); data.push_back(temp); size_t iHp = speciesIndex("H+"); if (iHp != npos) { double pH = -log(temp[iHp]) / log(10.0); csvFile << setw(tabL) << "pH = " << setw(tabS) << pH << endl; } } catch (CanteraError& err) { err.save(); } try { getPartialMolarEnthalpies(&temp[0]); pNames.push_back("Part. Mol Enthalpy (J/kmol)"); data.push_back(temp); } catch (CanteraError& err) { err.save(); } try { getPartialMolarEntropies(&temp[0]); pNames.push_back("Part. Mol. Entropy (J/K/kmol)"); data.push_back(temp); } catch (CanteraError& err) { err.save(); } try { getPartialMolarIntEnergies(&temp[0]); pNames.push_back("Part. Mol. Energy (J/kmol)"); data.push_back(temp); } catch (CanteraError& err) { err.save(); } try { getPartialMolarCp(&temp[0]); pNames.push_back("Part. Mol. Cp (J/K/kmol"); data.push_back(temp); } catch (CanteraError& err) { err.save(); } try { getPartialMolarVolumes(&temp[0]); pNames.push_back("Part. Mol. Cv (J/K/kmol)"); data.push_back(temp); } catch (CanteraError& err) { err.save(); } csvFile << endl << setw(tabS) << "Species,"; for (size_t i = 0; i < pNames.size(); i++) { csvFile << setw(tabM) << pNames[i] << ","; } csvFile << endl; /* csvFile.fill('-'); csvFile << setw(tabS+(tabM+1)*pNames.size()) << "-\n"; csvFile.fill(' '); */ for (size_t k = 0; k < nSpecies(); k++) { csvFile << setw(tabS) << speciesName(k) + ","; if (data[0][k] > SmallNumber) { for (size_t i = 0; i < pNames.size(); i++) { csvFile << setw(tabM) << data[i][k] << ","; } csvFile << endl; } else { for (size_t i = 0; i < pNames.size(); i++) { csvFile << setw(tabM) << 0 << ","; } csvFile << endl; } } } catch (CanteraError& err) { err.save(); } }
/** * Format a summary of the mixture state for output. */ std::string MolalityVPSSTP::report(bool show_thermo) const { char p[800]; string s = ""; try { if (name() != "") { sprintf(p, " \n %s:\n", name().c_str()); s += p; } sprintf(p, " \n temperature %12.6g K\n", temperature()); s += p; sprintf(p, " pressure %12.6g Pa\n", pressure()); s += p; sprintf(p, " density %12.6g kg/m^3\n", density()); s += p; sprintf(p, " mean mol. weight %12.6g amu\n", meanMolecularWeight()); s += p; doublereal phi = electricPotential(); sprintf(p, " potential %12.6g V\n", phi); s += p; size_t kk = nSpecies(); vector_fp x(kk); vector_fp molal(kk); vector_fp mu(kk); vector_fp muss(kk); vector_fp acMolal(kk); vector_fp actMolal(kk); getMoleFractions(&x[0]); getMolalities(&molal[0]); getChemPotentials(&mu[0]); getStandardChemPotentials(&muss[0]); getMolalityActivityCoefficients(&acMolal[0]); getActivities(&actMolal[0]); size_t iHp = speciesIndex("H+"); if (iHp != npos) { double pH = -log(actMolal[iHp]) / log(10.0); sprintf(p, " pH %12.4g \n", pH); s += p; } if (show_thermo) { sprintf(p, " \n"); s += p; sprintf(p, " 1 kg 1 kmol\n"); s += p; sprintf(p, " ----------- ------------\n"); s += p; sprintf(p, " enthalpy %12.6g %12.4g J\n", enthalpy_mass(), enthalpy_mole()); s += p; sprintf(p, " internal energy %12.6g %12.4g J\n", intEnergy_mass(), intEnergy_mole()); s += p; sprintf(p, " entropy %12.6g %12.4g J/K\n", entropy_mass(), entropy_mole()); s += p; sprintf(p, " Gibbs function %12.6g %12.4g J\n", gibbs_mass(), gibbs_mole()); s += p; sprintf(p, " heat capacity c_p %12.6g %12.4g J/K\n", cp_mass(), cp_mole()); s += p; try { sprintf(p, " heat capacity c_v %12.6g %12.4g J/K\n", cv_mass(), cv_mole()); s += p; } catch (CanteraError& err) { err.save(); sprintf(p, " heat capacity c_v <not implemented> \n"); s += p; } } sprintf(p, " \n"); s += p; if (show_thermo) { sprintf(p, " X " " Molalities Chem.Pot. ChemPotSS ActCoeffMolal\n"); s += p; sprintf(p, " " " (J/kmol) (J/kmol) \n"); s += p; sprintf(p, " ------------- " " ------------ ------------ ------------ ------------\n"); s += p; for (size_t k = 0; k < kk; k++) { if (x[k] > SmallNumber) { sprintf(p, "%18s %12.6g %12.6g %12.6g %12.6g %12.6g\n", speciesName(k).c_str(), x[k], molal[k], mu[k], muss[k], acMolal[k]); } else { sprintf(p, "%18s %12.6g %12.6g N/A %12.6g %12.6g \n", speciesName(k).c_str(), x[k], molal[k], muss[k], acMolal[k]); } s += p; } } else { sprintf(p, " X" "Molalities\n"); s += p; sprintf(p, " -------------" " ------------\n"); s += p; for (size_t k = 0; k < kk; k++) { sprintf(p, "%18s %12.6g %12.6g\n", speciesName(k).c_str(), x[k], molal[k]); s += p; } } } catch (CanteraError& err) { err.save(); } return s; }
std::string ThermoPhase::report(bool show_thermo, doublereal threshold) const { fmt::MemoryWriter b; try { if (name() != "") { b.write("\n {}:\n", name()); } b.write("\n"); b.write(" temperature {:12.6g} K\n", temperature()); b.write(" pressure {:12.6g} Pa\n", pressure()); b.write(" density {:12.6g} kg/m^3\n", density()); b.write(" mean mol. weight {:12.6g} amu\n", meanMolecularWeight()); doublereal phi = electricPotential(); if (phi != 0.0) { b.write(" potential {:12.6g} V\n", phi); } if (show_thermo) { b.write("\n"); b.write(" 1 kg 1 kmol\n"); b.write(" ----------- ------------\n"); b.write(" enthalpy {:12.5g} {:12.4g} J\n", enthalpy_mass(), enthalpy_mole()); b.write(" internal energy {:12.5g} {:12.4g} J\n", intEnergy_mass(), intEnergy_mole()); b.write(" entropy {:12.5g} {:12.4g} J/K\n", entropy_mass(), entropy_mole()); b.write(" Gibbs function {:12.5g} {:12.4g} J\n", gibbs_mass(), gibbs_mole()); b.write(" heat capacity c_p {:12.5g} {:12.4g} J/K\n", cp_mass(), cp_mole()); try { b.write(" heat capacity c_v {:12.5g} {:12.4g} J/K\n", cv_mass(), cv_mole()); } catch (NotImplementedError&) { b.write(" heat capacity c_v <not implemented> \n"); } } vector_fp x(m_kk); vector_fp y(m_kk); vector_fp mu(m_kk); getMoleFractions(&x[0]); getMassFractions(&y[0]); getChemPotentials(&mu[0]); int nMinor = 0; doublereal xMinor = 0.0; doublereal yMinor = 0.0; b.write("\n"); if (show_thermo) { b.write(" X " " Y Chem. Pot. / RT\n"); b.write(" ------------- " "------------ ------------\n"); for (size_t k = 0; k < m_kk; k++) { if (abs(x[k]) >= threshold) { if (abs(x[k]) > SmallNumber) { b.write("{:>18s} {:12.6g} {:12.6g} {:12.6g}\n", speciesName(k), x[k], y[k], mu[k]/RT()); } else { b.write("{:>18s} {:12.6g} {:12.6g}\n", speciesName(k), x[k], y[k]); } } else { nMinor++; xMinor += x[k]; yMinor += y[k]; } } } else { b.write(" X Y\n"); b.write(" ------------- ------------\n"); for (size_t k = 0; k < m_kk; k++) { if (abs(x[k]) >= threshold) { b.write("{:>18s} {:12.6g} {:12.6g}\n", speciesName(k), x[k], y[k]); } else { nMinor++; xMinor += x[k]; yMinor += y[k]; } } } if (nMinor) { b.write(" [{:+5d} minor] {:12.6g} {:12.6g}\n", nMinor, xMinor, yMinor); } } catch (CanteraError& err) { return b.str() + err.what(); } return b.str(); }
std::string MolalityVPSSTP::report(bool show_thermo, doublereal threshold) const { fmt::MemoryWriter b; try { if (name() != "") { b.write("\n {}:\n", name()); } b.write("\n"); b.write(" temperature {:12.6g} K\n", temperature()); b.write(" pressure {:12.6g} Pa\n", pressure()); b.write(" density {:12.6g} kg/m^3\n", density()); b.write(" mean mol. weight {:12.6g} amu\n", meanMolecularWeight()); doublereal phi = electricPotential(); b.write(" potential {:12.6g} V\n", phi); vector_fp x(m_kk); vector_fp molal(m_kk); vector_fp mu(m_kk); vector_fp muss(m_kk); vector_fp acMolal(m_kk); vector_fp actMolal(m_kk); getMoleFractions(&x[0]); getMolalities(&molal[0]); getChemPotentials(&mu[0]); getStandardChemPotentials(&muss[0]); getMolalityActivityCoefficients(&acMolal[0]); getActivities(&actMolal[0]); size_t iHp = speciesIndex("H+"); if (iHp != npos) { double pH = -log(actMolal[iHp]) / log(10.0); b.write(" pH {:12.4g}\n", pH); } if (show_thermo) { b.write("\n"); b.write(" 1 kg 1 kmol\n"); b.write(" ----------- ------------\n"); b.write(" enthalpy {:12.6g} {:12.4g} J\n", enthalpy_mass(), enthalpy_mole()); b.write(" internal energy {:12.6g} {:12.4g} J\n", intEnergy_mass(), intEnergy_mole()); b.write(" entropy {:12.6g} {:12.4g} J/K\n", entropy_mass(), entropy_mole()); b.write(" Gibbs function {:12.6g} {:12.4g} J\n", gibbs_mass(), gibbs_mole()); b.write(" heat capacity c_p {:12.6g} {:12.4g} J/K\n", cp_mass(), cp_mole()); try { b.write(" heat capacity c_v {:12.6g} {:12.4g} J/K\n", cv_mass(), cv_mole()); } catch (NotImplementedError& e) { b.write(" heat capacity c_v <not implemented>\n"); } } b.write("\n"); int nMinor = 0; doublereal xMinor = 0.0; if (show_thermo) { b.write(" X " " Molalities Chem.Pot. ChemPotSS ActCoeffMolal\n"); b.write(" " " (J/kmol) (J/kmol)\n"); b.write(" ------------- " " ------------ ------------ ------------ ------------\n"); for (size_t k = 0; k < m_kk; k++) { if (x[k] > threshold) { if (x[k] > SmallNumber) { b.write("{:>18s} {:12.6g} {:12.6g} {:12.6g} {:12.6g} {:12.6g}\n", speciesName(k), x[k], molal[k], mu[k], muss[k], acMolal[k]); } else { b.write("{:>18s} {:12.6g} {:12.6g} N/A {:12.6g} {:12.6g}\n", speciesName(k), x[k], molal[k], muss[k], acMolal[k]); } } else { nMinor++; xMinor += x[k]; } } } else { b.write(" X" "Molalities\n"); b.write(" -------------" " ------------\n"); for (size_t k = 0; k < m_kk; k++) { if (x[k] > threshold) { b.write("{:>18s} {:12.6g} {:12.6g}\n", speciesName(k), x[k], molal[k]); } else { nMinor++; xMinor += x[k]; } } } if (nMinor) { b.write(" [{:+5d} minor] {:12.6g}\n", nMinor, xMinor); } } catch (CanteraError& err) { return b.str() + err.what(); } return b.str(); }
doublereal MixtureFugacityTP::z() const { return pressure() * meanMolecularWeight() / (density() * _RT()); }
doublereal LatticePhase::calcDensity() { setMolarDensity(m_site_density); return meanMolecularWeight() * m_site_density; }
doublereal MixtureFugacityTP::densityCalc(doublereal TKelvin, doublereal presPa, int phase, doublereal rhoguess) { doublereal tcrit = critTemperature(); doublereal mmw = meanMolecularWeight(); if (rhoguess == -1.0) { if (phase != -1) { if (TKelvin > tcrit) { rhoguess = presPa * mmw / (GasConstant * TKelvin); } else { if (phase == FLUID_GAS || phase == FLUID_SUPERCRIT) { rhoguess = presPa * mmw / (GasConstant * TKelvin); } else if (phase >= FLUID_LIQUID_0) { double lqvol = liquidVolEst(TKelvin, presPa); rhoguess = mmw / lqvol; } } } else { /* * Assume the Gas phase initial guess, if nothing is * specified to the routine */ rhoguess = presPa * mmw / (GasConstant * TKelvin); } } double molarVolBase = mmw / rhoguess; double molarVolLast = molarVolBase; double vc = mmw / critDensity(); /* * molar volume of the spinodal at the current temperature and mole fractions. this will * be updated as we go. */ double molarVolSpinodal = vc; bool conv = false; /* * We start on one side of the vc and stick with that side */ bool gasSide = molarVolBase > vc; if (gasSide) { molarVolLast = (GasConstant * TKelvin)/presPa; } else { molarVolLast = liquidVolEst(TKelvin, presPa); } /* * OK, now we do a small solve to calculate the molar volume given the T,P value. * The algorithm is taken from dfind() */ for (int n = 0; n < 200; n++) { /* * Calculate the predicted reduced pressure, pred0, based on the * current tau and dd. */ /* * Calculate the derivative of the predicted pressure * wrt the molar volume. * This routine also returns the pressure, presBase */ double presBase; double dpdVBase = dpdVCalc(TKelvin, molarVolBase, presBase); /* * If dpdV is positve, then we are in the middle of the * 2 phase region and beyond the spinodal stability curve. We need to adjust * the initial guess outwards and start a new iteration. */ if (dpdVBase >= 0.0) { if (TKelvin > tcrit) { throw CanteraError("MixtureFugacityTP::densityCalc", "T > tcrit unexpectedly"); } /* * TODO Spawn a calculation for the value of the spinodal point that is * very accurate. Answer the question as to wethera solution is * possible on the current side of the vapor dome. */ if (gasSide) { if (molarVolBase >= vc) { molarVolSpinodal = molarVolBase; molarVolBase = 0.5 * (molarVolLast + molarVolSpinodal); } else { molarVolBase = 0.5 * (molarVolLast + molarVolSpinodal); } } else { if (molarVolBase <= vc) { molarVolSpinodal = molarVolBase; molarVolBase = 0.5 * (molarVolLast + molarVolSpinodal); } else { molarVolBase = 0.5 * (molarVolLast + molarVolSpinodal); } } continue; } /* * Check for convergence */ if (fabs(presBase-presPa) < 1.0E-30 + 1.0E-8 * presPa) { conv = true; break; } /* * Dampen and crop the update */ doublereal dpdV = dpdVBase; if (n < 10) { dpdV = dpdVBase * 1.5; } /* * Formulate the update to the molar volume by * Newton's method. Then, crop it to a max value * of 0.1 times the current volume */ double delMV = - (presBase - presPa) / dpdV; if (!gasSide || delMV < 0.0) { if (fabs(delMV) > 0.2 * molarVolBase) { delMV = delMV / fabs(delMV) * 0.2 * molarVolBase; } } /* * Only go 1/10 the way towards the spinodal at any one time. */ if (TKelvin < tcrit) { if (gasSide) { if (delMV < 0.0) { if (-delMV > 0.5 * (molarVolBase - molarVolSpinodal)) { delMV = - 0.5 * (molarVolBase - molarVolSpinodal); } } } else { if (delMV > 0.0) { if (delMV > 0.5 * (molarVolSpinodal - molarVolBase)) { delMV = 0.5 * (molarVolSpinodal - molarVolBase); } } } } /* * updated the molar volume value */ molarVolLast = molarVolBase; molarVolBase += delMV; if (fabs(delMV/molarVolBase) < 1.0E-14) { conv = true; break; } /* * Check for negative molar volumes */ if (molarVolBase <= 0.0) { molarVolBase = std::min(1.0E-30, fabs(delMV*1.0E-4)); } } /* * Check for convergence, and return 0.0 if it wasn't achieved. */ double densBase = 0.0; if (! conv) { molarVolBase = 0.0; throw CanteraError("MixtureFugacityTP::densityCalc()", "Process didnot converge"); } else { densBase = mmw / molarVolBase; } return densBase; }
std::string MolarityIonicVPSSTP::report(bool show_thermo) const { char p[800]; string s = ""; try { if (name() != "") { sprintf(p, " \n %s:\n", name().c_str()); s += p; } sprintf(p, " \n temperature %12.6g K\n", temperature()); s += p; sprintf(p, " pressure %12.6g Pa\n", pressure()); s += p; sprintf(p, " density %12.6g kg/m^3\n", density()); s += p; sprintf(p, " mean mol. weight %12.6g amu\n", meanMolecularWeight()); s += p; doublereal phi = electricPotential(); sprintf(p, " potential %12.6g V\n", phi); s += p; size_t kk = nSpecies(); vector_fp x(kk); vector_fp molal(kk); vector_fp mu(kk); vector_fp muss(kk); vector_fp acMolal(kk); vector_fp actMolal(kk); getMoleFractions(&x[0]); getChemPotentials(&mu[0]); getStandardChemPotentials(&muss[0]); getActivities(&actMolal[0]); if (show_thermo) { sprintf(p, " \n"); s += p; sprintf(p, " 1 kg 1 kmol\n"); s += p; sprintf(p, " ----------- ------------\n"); s += p; sprintf(p, " enthalpy %12.6g %12.4g J\n", enthalpy_mass(), enthalpy_mole()); s += p; sprintf(p, " internal energy %12.6g %12.4g J\n", intEnergy_mass(), intEnergy_mole()); s += p; sprintf(p, " entropy %12.6g %12.4g J/K\n", entropy_mass(), entropy_mole()); s += p; sprintf(p, " Gibbs function %12.6g %12.4g J\n", gibbs_mass(), gibbs_mole()); s += p; sprintf(p, " heat capacity c_p %12.6g %12.4g J/K\n", cp_mass(), cp_mole()); s += p; try { sprintf(p, " heat capacity c_v %12.6g %12.4g J/K\n", cv_mass(), cv_mole()); s += p; } catch (CanteraError& e) { e.save(); sprintf(p, " heat capacity c_v <not implemented> \n"); s += p; } } } catch (CanteraError& e) { e.save(); } return s; }
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; }