Added code for liquid enthalpy ancillary for Propane - proof of principle.

Signed-off-by: Ian Bell <ian.h.bell@gmail.com>
This commit is contained in:
Ian Bell
2014-07-31 19:39:24 +02:00
parent 33b5fe0e28
commit fc7eb55ca2
8 changed files with 174 additions and 39 deletions

View File

@@ -53,7 +53,7 @@ void FlashRoutines::QT_flash(HelmholtzEOSMixtureBackend &HEOS)
rhoLsat = HEOS.solver_rho_Tp(HEOS._T, psatLanc, rhoLanc);
rhoVsat = HEOS.solver_rho_Tp(HEOS._T, psatVanc, rhoVanc);
if (!ValidNumber(rhoLsat) || !ValidNumber(rhoVsat) ||
fabs(rhoLsat/rhoLanc-1) > 0.1 || fabs(rhoVanc/rhoVsat-1) > 0.1)
fabs(rhoLsat/rhoLanc-1) > 0.5 || fabs(rhoVanc/rhoVsat-1) > 0.5)
{
throw ValueError("pseudo-pure failed");
}
@@ -325,9 +325,59 @@ void FlashRoutines::PHSU_D_flash(HelmholtzEOSMixtureBackend &HEOS, int other)
throw NotImplementedError("PHSU_D_flash not ready for mixtures");
}
}
void FlashRoutines::HSU_P_flash_singlephase(HelmholtzEOSMixtureBackend &HEOS, int other, long double T0, long double rhomolar0)
{
}
void FlashRoutines::HSU_P_flash(HelmholtzEOSMixtureBackend &HEOS, int other)
{
throw NotImplementedError("HSU_P_flash Not implemented yet");
if (HEOS.imposed_phase_index > -1)
{
// Use the phase defined by the imposed phase
HEOS._phase = HEOS.imposed_phase_index;
}
else
{
if (HEOS.is_pure_or_pseudopure)
{
// Find the phase, while updating all internal variables possible
switch (other)
{
case iSmolar:
HEOS.p_phase_determination_pure_or_pseudopure(iSmolar, HEOS._smolar); break;
case iHmolar:
HEOS.p_phase_determination_pure_or_pseudopure(iHmolar, HEOS._hmolar); break;
case iUmolar:
HEOS.p_phase_determination_pure_or_pseudopure(iUmolar, HEOS._umolar); break;
default:
throw ValueError(format("Input for other [%s] is invalid", get_parameter_information(other, "long").c_str()));
}
}
else
{
HEOS._phase = iphase_gas;
throw NotImplementedError("HSU_P_flash does not support mixtures (yet)");
// Find the phase, while updating all internal variables possible
}
}
if (HEOS.isHomogeneousPhase() && !ValidNumber(HEOS._p))
{
switch (other)
{
case iDmolar:
break;
case iHmolar:
HEOS._rhomolar = HEOS.solver_for_rho_given_T_oneof_HSU(HEOS._T, HEOS._hmolar, iHmolar); break;
case iSmolar:
HEOS._rhomolar = HEOS.solver_for_rho_given_T_oneof_HSU(HEOS._T, HEOS._smolar, iSmolar); break;
case iUmolar:
HEOS._rhomolar = HEOS.solver_for_rho_given_T_oneof_HSU(HEOS._T, HEOS._umolar, iUmolar); break;
default:
break;
}
HEOS.calc_pressure();
HEOS._Q = -1;
}
}
void FlashRoutines::DHSU_T_flash(HelmholtzEOSMixtureBackend &HEOS, int other)
{

View File

@@ -49,6 +49,13 @@ public:
/// @param other The index for the other input from CoolProp::parameters; allowed values are iHmolar, iSmolar, iUmolar
static void HSU_P_flash(HelmholtzEOSMixtureBackend &HEOS, int other);
/// The single-phase flash routine for the pairs (P,H), (P,S), and (P,U). Similar analysis is needed
/// @param HEOS The HelmholtzEOSMixtureBackend to be used
/// @param other The index for the other input from CoolProp::parameters; allowed values are iHmolar, iSmolar, iUmolar
/// @param T0 The initial guess value for the temperature [K]
/// @param rho0 The initial guess value for the density [mol/m^3]
static void HSU_P_flash_singlephase(HelmholtzEOSMixtureBackend &HEOS, int other, long double T0, long double rhomolar0);
/// A generic flash routine for the pairs (D,P), (D,H), (D,S), and (D,U). Similar analysis is needed
/// @param HEOS The HelmholtzEOSMixtureBackend to be used
/// @param other The index for the other input from CoolProp::parameters; allowed values are iP, iHmolar, iSmolar, iUmolar
@@ -56,4 +63,4 @@ public:
};
} /* namespace CoolProp */
#endif /* FLASHROUTINES_H */
#endif /* FLASHROUTINES_H */

View File

@@ -926,6 +926,16 @@ protected:
fluid.ancillaries.pV = SaturationAncillaryFunction(ancillaries["pV"]);
fluid.ancillaries.rhoL = SaturationAncillaryFunction(ancillaries["rhoL"]);
fluid.ancillaries.rhoV = SaturationAncillaryFunction(ancillaries["rhoV"]);
if (ancillaries.HasMember("hL"))
{
fluid.ancillaries.hL = SaturationAncillaryFunction(ancillaries["hL"]);
}
else
{
if (get_debug_level() > 0){ std::cout << "Missing hL ancillary for fluid " << fluid.name; }
}
};
/// Parse the surface_tension

View File

@@ -625,6 +625,7 @@ void HelmholtzEOSMixtureBackend::p_phase_determination_pure_or_pseudopure(int ot
switch (other)
{
// First try the ancillaries, use them to determine the state if you can
case iT:
{
long double p_vap = 0.98*static_cast<double>(_pVanc);
@@ -638,6 +639,28 @@ void HelmholtzEOSMixtureBackend::p_phase_determination_pure_or_pseudopure(int ot
}
break;
}
case iHmolar:
{
long double h_liq = components[0]->ancillaries.hL.evaluate(_TLanc);
long double h_vap = components[0]->ancillaries.hV.evaluate(_T);
// Check if in range given the accuracy of the fit
if (value > h_vap + components[0]->ancillaries.hV.get_max_abs_error()){
this->_phase = iphase_gas; _Q = -1000; return;
}
else if (value < h_liq - components[0]->ancillaries.hL.get_max_abs_error()){
this->_phase = iphase_liquid; _Q = 1000; return;
}
break;
}
case iSmolar:
{
// Add entropy ancillary code here
}
case iUmolar:
{
// Add entropy ancillary code here
}
default:
{
// Always calculate the densities using the ancillaries