-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove penalization in fugacity computations and improve Gibbs energy calculation #5
base: master
Are you sure you want to change the base?
Changes from all commits
afea63e
bb7ed6b
f64d2fb
6b6af9e
5310496
a71d8ca
7d5fbf8
4cbf627
5dd15d4
96cfee3
60f9206
adff826
837d5e7
12ee1e8
b0fc3ae
45c92b4
39a35ef
8215c84
951b4e6
b464378
fba8e38
8466980
8b22d0d
8e0e84e
96da719
5ad0328
fd4eb12
4919ff2
2f18f46
b23efeb
e78f257
fbace21
17a1d8a
0780086
abdca09
2eb0381
3311073
ef163e2
7f17d2d
56bb082
2556c3d
633afbd
df2caad
e99016e
1fdfb9a
04fa0db
91b25eb
f251727
6e1961e
1ceaf37
0e29074
4cc33af
a08d878
669c193
1f91ad0
d3a73fd
dcb2e8e
d64160e
35a34a7
ff05efb
f5db28c
ff3c7af
c7a595b
a2a6b0b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
dependencies: | ||
- numpy | ||
- pandas | ||
- matplotlib | ||
- pip | ||
- tabulate | ||
- colorama | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -321,6 +321,13 @@ auto ChemicalProperties::phaseSpecificVolumes() const -> ChemicalVector | |
return phaseAmounts()/phaseMasses() % phaseMolarVolumes(); | ||
} | ||
|
||
auto ChemicalProperties::phaseCompressibilityFactors() const -> ChemicalVector | ||
{ | ||
const auto& R = universalGasConstant; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am curious. Why did you use |
||
const auto& v = phaseMolarVolumes(); | ||
return P * v / (R * T); | ||
} | ||
|
||
auto ChemicalProperties::phaseSpecificEntropies() const -> ChemicalVector | ||
{ | ||
return phaseAmounts()/phaseMasses() % phaseMolarEntropies(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -156,6 +156,131 @@ auto Psi(CubicEOS::Model type) -> double | |
|
||
} // namespace internal | ||
|
||
auto computeSpeciesFugacity( | ||
const ThermoScalar& P, | ||
const ThermoScalar& T, | ||
const ChemicalScalar& xi, | ||
const ChemicalScalar& ai, | ||
const double& bi, | ||
const ChemicalScalar& aiT, | ||
const ChemicalScalar& amix, | ||
const ChemicalScalar& amixT, | ||
const ChemicalScalar& bmix, | ||
const ChemicalScalar& A, | ||
const ChemicalScalar& B, | ||
const ChemicalScalar& C, | ||
const ChemicalScalar& Z, | ||
const double epsilon, | ||
const double sigma) -> ChemicalScalar | ||
{ | ||
const double R = universalGasConstant; | ||
|
||
const double almost_zero = 1e-20; | ||
|
||
const ChemicalScalar q = amix/(bmix*R*T); | ||
const ChemicalScalar qT = q*(amixT/amix - 1.0/T); | ||
|
||
const ChemicalScalar beta = P*bmix/(R*T); | ||
const ThermoScalar betai = P*bi/(R*T); | ||
|
||
const ChemicalScalar qi = q*(1 + ai/amix - bi/bmix); | ||
const ChemicalScalar qiT = qi*qT/q + q*(aiT - ai*amixT/amix)/amix; | ||
|
||
const ThermoScalar Ai = (epsilon + sigma - 1.0)*betai - 1.0; | ||
const ChemicalScalar Bi = (epsilon*sigma - epsilon - sigma)*(2*beta*betai - beta*beta) - (epsilon + sigma - q)*(betai - beta) - (epsilon + sigma - qi)*beta; | ||
const ChemicalScalar Ci = -3*sigma*epsilon*beta*beta*betai + 2*epsilon*sigma*beta*beta*beta - (epsilon*sigma + qi)*beta*beta - 2*(epsilon*sigma + q)*(beta*betai - beta*beta); | ||
const ChemicalScalar Zi = -(Ai*Z*Z + (Bi + B)*Z + Ci + 2*C)/(3*Z*Z + 2*A*Z + B); | ||
|
||
// Calculate the integration factor I | ||
ChemicalScalar I; | ||
if(std::abs(epsilon - sigma) > almost_zero) I = log((Z + sigma*beta)/(Z + epsilon*beta))/(sigma - epsilon); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMHO, assignments like this would be more legible if you use a ternary operator, or even curly brackets in each block. |
||
else I = beta/(Z + epsilon*beta); | ||
|
||
// Calculate the integration factor I for each component | ||
ChemicalScalar Ii; | ||
if(std::abs(epsilon - sigma) > almost_zero) Ii = I + ((Zi + sigma*betai)/(Z + sigma*beta) - (Zi + epsilon*betai)/(Z + epsilon*beta))/(sigma - epsilon); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here |
||
else Ii = I * (1 + betai/beta - (Zi + epsilon*betai)/(Z + epsilon*beta)); | ||
|
||
auto Gi_res = R*T*(Zi - (Zi - betai)/(Z - beta) - log(Z - beta) - qi*I - q*Ii + q*I); | ||
auto ln_fi = Gi_res/(R*T) + log(xi * P); | ||
auto fi = exp(ln_fi); | ||
return fi; | ||
} | ||
|
||
auto calculateNormalizedPhaseGibbsEnergy( | ||
const unsigned& nspecies, | ||
const ThermoScalar& P, | ||
const ThermoScalar& T, | ||
const ChemicalVector& x, | ||
const ChemicalVector& abar, | ||
const Vector& bbar, | ||
const ChemicalVector& abarT, | ||
const ChemicalScalar& amix, | ||
const ChemicalScalar& amixT, | ||
const ChemicalScalar& bmix, | ||
const ChemicalScalar& A, | ||
const ChemicalScalar& B, | ||
const ChemicalScalar& C, | ||
const ChemicalScalar& Z, | ||
const double epsilon, | ||
const double sigma) -> ChemicalScalar | ||
{ | ||
ChemicalScalar G_normalized; | ||
for(unsigned i = 0; i < nspecies; ++i) | ||
{ | ||
auto xi = x[i]; | ||
auto fi = computeSpeciesFugacity(P, T, xi, abar[i], bbar[i], abarT[i], amix, amixT, bmix, A, B, C, Z, epsilon, sigma); | ||
G_normalized += xi * log(fi); | ||
} | ||
return G_normalized; | ||
} | ||
|
||
auto selectCompressibilityFactorByGibbsEnergy( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this function unused? |
||
const unsigned& nspecies, | ||
std::vector<ChemicalScalar> Zs, | ||
const ThermoScalar& P, | ||
const ThermoScalar& T, | ||
const ChemicalVector& x, | ||
const ChemicalVector& abar, | ||
const Vector& bbar, | ||
const ChemicalVector& abarT, | ||
const ChemicalScalar& amix, | ||
const ChemicalScalar& amixT, | ||
const ChemicalScalar& bmix, | ||
const ChemicalScalar& A, | ||
const ChemicalScalar& B, | ||
const ChemicalScalar& C, | ||
const double epsilon, | ||
const double sigma) -> ChemicalScalar | ||
{ | ||
ChemicalScalar Z(nspecies); | ||
if (Zs.size() == 1) | ||
{ | ||
Z = Zs[0]; | ||
return Z; | ||
} | ||
|
||
if (Zs.size() != 2) { | ||
Exception exception; | ||
exception.error << "selectCompressibilityByGibbsEnergy received invalid input"; | ||
exception.reason << "Zs should have size 1 or 2 in selectCompressibilityByGibbsEnergy, " | ||
<< "but has a size of " << Zs.size(); | ||
RaiseError(exception); | ||
} | ||
|
||
std::vector<ChemicalScalar> normalized_Gs; | ||
normalized_Gs.push_back( | ||
calculateNormalizedPhaseGibbsEnergy(nspecies, P, T, x, abar, bbar, abarT, amix, amixT, bmix, A, B, C, Zs[0], epsilon, sigma) | ||
); | ||
normalized_Gs.push_back( | ||
calculateNormalizedPhaseGibbsEnergy(nspecies, P, T, x, abar, bbar, abarT, amix, amixT, bmix, A, B, C, Zs[1], epsilon, sigma) | ||
); | ||
|
||
Z = normalized_Gs[0] < normalized_Gs[1] ? Zs[0] : Zs[1]; | ||
|
||
return Z; | ||
} | ||
|
||
struct CubicEOS::Impl | ||
{ | ||
/// The number of species in the phase. | ||
|
@@ -340,11 +465,15 @@ struct CubicEOS::Impl | |
const auto cubic_size = cubicEOS_roots.size(); | ||
|
||
std::vector<ChemicalScalar> Zs; | ||
if (cubic_size == 1 || cubic_size == 2) | ||
if (cubic_size == 1) | ||
{ | ||
//even if cubicEOS_roots has 2 roots, assume that the smallest does not have physical meaning | ||
Zs.push_back(ChemicalScalar(nspecies, cubicEOS_roots[0])); | ||
} | ||
else if (cubic_size == 2) | ||
{ | ||
Zs.push_back(ChemicalScalar(nspecies, cubicEOS_roots[0])); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid temporary objects, use |
||
Zs.push_back(ChemicalScalar(nspecies, cubicEOS_roots[1])); | ||
} | ||
else | ||
{ | ||
if (cubic_size != 3) { | ||
|
@@ -357,16 +486,18 @@ struct CubicEOS::Impl | |
Zs.push_back(ChemicalScalar(nspecies, cubicEOS_roots[2])); // Z_min | ||
} | ||
|
||
// Selecting compressibility factor - Z_liq < Z_gas | ||
ChemicalScalar Z(nspecies); | ||
|
||
// Selecting compressibility factor - Z_liq < Z_gas | ||
//TODO: study the possibilty to use selectCompressibilityFactorByGibbsEnergy for Z selection | ||
if (isvapor) | ||
Z.val = *std::max_element(cubicEOS_roots.begin(), cubicEOS_roots.end()); | ||
else | ||
Z.val = *std::min_element(cubicEOS_roots.begin(), cubicEOS_roots.end()); | ||
|
||
auto input_phase_type = isvapor ? PhaseType::Gas : PhaseType::Liquid; | ||
auto identified_phase_type = input_phase_type; | ||
|
||
auto identified_phase_type = input_phase_type; | ||
switch (phase_identification_method) | ||
{ | ||
case PhaseIdentificationMethod::None: | ||
|
@@ -390,8 +521,7 @@ struct CubicEOS::Impl | |
throw std::logic_error("CubicEOS received an unexpected phaseIdentificationMethod"); | ||
} | ||
|
||
if (identified_phase_type != input_phase_type) | ||
{ | ||
if (identified_phase_type != input_phase_type) { | ||
// Since the phase is identified as different than the expect input phase type, it is | ||
// deemed inappropriate. Artificially high values are configured for fugacities, so that | ||
// this condition is "removed" by the optimizer. | ||
|
@@ -403,7 +533,7 @@ struct CubicEOS::Impl | |
result.partial_molar_volumes.fill(0.0); | ||
result.residual_partial_molar_gibbs_energies.fill(0.0); | ||
result.residual_partial_molar_enthalpies.fill(0.0); | ||
result.ln_fugacity_coefficients.fill(100.0); | ||
result.ln_fugacity_coefficients.fill(0.0); | ||
return result; | ||
} | ||
|
||
|
@@ -493,7 +623,7 @@ CubicEOS::Result::Result(unsigned nspecies) | |
{} | ||
|
||
/// Sanity check free function to verify if BIPs matrices have proper dimensions. Considering that the phase has | ||
/// n species, the BIP matricies k, kT and kTT should have (n, n) as dimensions. | ||
/// n species, the BIP matrices k, kT and kTT should have (n, n) as dimensions. | ||
/// @see CubicEOS::setInteractionParamsFunction | ||
auto sanityCheckInteractionParamsFunction(const unsigned& nspecies, const CubicEOS::InteractionParamsFunction& func) -> void | ||
{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -107,6 +107,38 @@ auto pressureComparison(const ThermoScalar& Pressure, const ThermoScalar& Temper | |
RaiseError(exception); | ||
} | ||
|
||
auto computeGibbsResidualEnergy( | ||
alexandrebbruno marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const ThermoScalar& pressure, | ||
const ThermoScalar& temperature, | ||
const ChemicalScalar& amix, | ||
const ChemicalScalar& bmix, | ||
const ChemicalScalar& A, | ||
const ChemicalScalar& B, | ||
const ChemicalScalar& Z, | ||
const double epsilon, | ||
const double sigma) -> ChemicalScalar | ||
{ | ||
auto const almost_zero = 1e-20; | ||
auto constexpr R = universalGasConstant; | ||
auto const& T = temperature; | ||
|
||
// Computing the values of residual Gibbs energy for all Zs | ||
ChemicalScalar Gs; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor, but it doesn't seem necessary to have this uninitialized variable here, line 138 could be |
||
const double factor = -1.0 / (3 * Z.val*Z.val + 2 * A.val*Z.val + B.val); | ||
const ChemicalScalar beta = pressure * bmix / (R * T); | ||
const ChemicalScalar q = amix / (bmix * R * T); | ||
|
||
// Calculate the integration factor I | ||
ChemicalScalar I; | ||
if (std::abs(epsilon - sigma) > almost_zero) | ||
I = log((Z + sigma * beta) / (Z + epsilon * beta)) / (sigma - epsilon); | ||
else | ||
I = beta / (Z + epsilon * beta); | ||
|
||
Gs = R * temperature*(Z - 1 - log(Z - beta) - q * I); | ||
|
||
return Gs; | ||
} | ||
|
||
auto gibbsResidualEnergyComparison( | ||
const ThermoScalar& pressure, | ||
|
@@ -127,24 +159,24 @@ auto gibbsResidualEnergyComparison( | |
std::vector<ChemicalScalar> Gs; | ||
for (const auto Z : {Z_max, Z_min}) | ||
{ | ||
const double factor = -1.0 / (3 * Z.val*Z.val + 2 * A.val*Z.val + B.val); | ||
const ChemicalScalar beta = pressure * bmix / (R * T); | ||
const ChemicalScalar q = amix / (bmix * R * T); | ||
|
||
// Calculate the integration factor I and its temperature derivative IT | ||
ChemicalScalar I; | ||
if (epsilon != sigma) | ||
I = log((Z + sigma * beta) / (Z + epsilon * beta)) / (sigma - epsilon); | ||
else | ||
I = beta / (Z + epsilon * beta); | ||
|
||
Gs.push_back(R * temperature*(Z - 1 - log(Z - beta) - q * I)); | ||
auto current_G = computeGibbsResidualEnergy( | ||
pressure, | ||
temperature, | ||
amix, | ||
bmix, | ||
A, | ||
B, | ||
Z, | ||
epsilon, | ||
sigma | ||
); | ||
|
||
Gs.push_back(current_G); | ||
} | ||
|
||
return (Gs[0].val < Gs[1].val) ? PhaseType::Gas : PhaseType::Liquid; | ||
} | ||
|
||
|
||
auto identifyPhaseUsingGibbsEnergyAndEos( | ||
const ThermoScalar& pressure, | ||
const ThermoScalar& temperature, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps this one could also be removed?