mirror of
https://github.com/Cantera/cantera.git
synced 2025-02-25 18:55:29 -06:00
Merge 5249dcef21
into 0720efb02d
This commit is contained in:
commit
2c5f9bd808
@ -366,7 +366,7 @@ public:
|
||||
* @param p Pressure (Pa)
|
||||
* @since New in %Cantera 3.0.
|
||||
*/
|
||||
void setState_DP(double rho, double p) override {
|
||||
void setState_DP(double rho, double p, double Tguess=300) override {
|
||||
if (p <= 0) {
|
||||
throw CanteraError("IdealGasPhase::setState_DP",
|
||||
"pressure must be positive");
|
||||
|
@ -88,7 +88,7 @@ public:
|
||||
* -1 means gas. The value -2 means unrestricted. Values of zero or
|
||||
* greater refer to species dominated condensed phases.
|
||||
*/
|
||||
void setForcedSolutionBranch(int solnBranch);
|
||||
void setForcedSolutionBranch(int solnBranch) override;
|
||||
|
||||
//! Report the solution branch which the solution is restricted to
|
||||
/*!
|
||||
|
@ -203,6 +203,7 @@ protected:
|
||||
* These are stored internally.
|
||||
*/
|
||||
double daAlpha_dT() const;
|
||||
double daAlpha_dT(double& temp) const;
|
||||
|
||||
//! Calculate second derivative @f$ d^2(a \alpha)/dT^2 @f$
|
||||
/*!
|
||||
@ -211,6 +212,7 @@ protected:
|
||||
double d2aAlpha_dT2() const;
|
||||
|
||||
public:
|
||||
void setState_DP(double rho, double p, double Tguess=300) override;
|
||||
|
||||
double isothermalCompressibility() const override;
|
||||
double thermalExpansionCoeff() const override;
|
||||
@ -229,7 +231,7 @@ public:
|
||||
* the internal numbers based on the state of the object.
|
||||
*/
|
||||
void updateMixingExpressions() override;
|
||||
|
||||
void updateMixingExpressions(double& temp,double& aCalc, double& bCalc, double& aAlphaCalc);
|
||||
//! Calculate the @f$ a @f$, @f$ b @f$, and @f$ \alpha @f$ parameters given the temperature
|
||||
/*!
|
||||
* This function doesn't change the internal state of the object, so it is a
|
||||
|
@ -1401,10 +1401,18 @@ public:
|
||||
* @param p Pressure (Pa)
|
||||
* @since New in %Cantera 3.0.
|
||||
*/
|
||||
virtual void setState_DP(double rho, double p) {
|
||||
virtual void setState_DP(double rho, double p, double Tguess=300) {
|
||||
throw NotImplementedError("ThermoPhase::setState_DP",
|
||||
"Not implemented for phase type '{}'", type());
|
||||
}
|
||||
//! Set the solution branch to force the ThermoPhase to exist on one branch
|
||||
//! or another
|
||||
/*!
|
||||
* @param solnBranch Branch that the solution is restricted to. the value
|
||||
* -1 means gas. The value -2 means unrestricted. Values of zero or
|
||||
* greater refer to species dominated condensed phases.
|
||||
*/
|
||||
virtual void setForcedSolutionBranch(int solnBranch){};
|
||||
|
||||
//! Set the state using an AnyMap containing any combination of properties
|
||||
//! supported by the thermodynamic model
|
||||
|
@ -835,7 +835,8 @@ int MixtureFugacityTP::solveCubic(double T, double pres, double a, double b,
|
||||
if (fabs(fabs(h) - fabs(yN)) < 1.0E-10) {
|
||||
if (disc > 1e-10) {
|
||||
throw CanteraError("MixtureFugacityTP::solveCubic",
|
||||
"value of yN and h are too high, unrealistic roots may be obtained");
|
||||
"value of yN and h are too high, unrealistic roots may be obtained"
|
||||
);
|
||||
}
|
||||
disc = 0.0;
|
||||
}
|
||||
|
@ -673,6 +673,28 @@ void PengRobinson::updateMixingExpressions()
|
||||
calculateAB(m_a,m_b,m_aAlpha_mix);
|
||||
}
|
||||
|
||||
|
||||
void PengRobinson::updateMixingExpressions(double& temp,double& aCalc, double& bCalc, double& aAlphaCalc)
|
||||
{
|
||||
//double temp = temperature();
|
||||
|
||||
// Update individual alpha
|
||||
for (size_t j = 0; j < m_kk; j++) {
|
||||
double critTemp_j = speciesCritTemperature(m_a_coeffs(j,j), m_b_coeffs[j]);
|
||||
double sqt_alpha = 1 + m_kappa[j] * (1 - sqrt(temp / critTemp_j));
|
||||
m_alpha[j] = sqt_alpha*sqt_alpha;
|
||||
}
|
||||
|
||||
// Update aAlpha_i, j
|
||||
for (size_t i = 0; i < m_kk; i++) {
|
||||
for (size_t j = 0; j < m_kk; j++) {
|
||||
m_aAlpha_binary(i, j) = sqrt(m_alpha[i] * m_alpha[j]) * m_a_coeffs(i,j);
|
||||
}
|
||||
}
|
||||
calculateAB(aCalc,bCalc,aAlphaCalc);
|
||||
}
|
||||
|
||||
|
||||
void PengRobinson::calculateAB(double& aCalc, double& bCalc, double& aAlphaCalc) const
|
||||
{
|
||||
bCalc = 0.0;
|
||||
@ -710,6 +732,30 @@ double PengRobinson::daAlpha_dT() const
|
||||
return daAlphadT;
|
||||
}
|
||||
|
||||
double PengRobinson::daAlpha_dT(double& temp) const
|
||||
{
|
||||
double daAlphadT = 0.0, k, Tc, sqtTr, coeff1, coeff2;
|
||||
for (size_t i = 0; i < m_kk; i++) {
|
||||
// Calculate first derivative of alpha for individual species
|
||||
Tc = speciesCritTemperature(m_a_coeffs(i,i), m_b_coeffs[i]);
|
||||
sqtTr = sqrt(temp / Tc);
|
||||
coeff1 = 1 / (Tc*sqtTr);
|
||||
coeff2 = sqtTr - 1;
|
||||
k = m_kappa[i];
|
||||
m_dalphadT[i] = coeff1 * (k*k*coeff2 - k);
|
||||
}
|
||||
// Calculate mixture derivative
|
||||
for (size_t i = 0; i < m_kk; i++) {
|
||||
for (size_t j = 0; j < m_kk; j++) {
|
||||
daAlphadT += moleFractions_[i] * moleFractions_[j] * 0.5
|
||||
* m_aAlpha_binary(i, j)
|
||||
* (m_dalphadT[i] / m_alpha[i] + m_dalphadT[j] / m_alpha[j]);
|
||||
}
|
||||
}
|
||||
return daAlphadT;
|
||||
}
|
||||
|
||||
|
||||
double PengRobinson::d2aAlpha_dT2() const
|
||||
{
|
||||
for (size_t i = 0; i < m_kk; i++) {
|
||||
@ -792,4 +838,45 @@ AnyMap PengRobinson::getAuxiliaryData()
|
||||
return parameters;
|
||||
}
|
||||
|
||||
void PengRobinson::setState_DP(double rho, double p, double Tguess)
|
||||
{
|
||||
if (p <= 0 || rho<=0 ) {
|
||||
throw CanteraError("PengRobinson::setState_DP",
|
||||
"pressure and density must be positive");
|
||||
}
|
||||
setDensity(rho);
|
||||
double mV = meanMolecularWeight() / rho;
|
||||
// Update individual alpha
|
||||
double aCalc, bCalc, aAlpha;
|
||||
int iteration = 0;
|
||||
double T_new = Tguess; //(p + term2) * denum / GasConstant;
|
||||
double p_iter=p;
|
||||
while (iteration < 300) {
|
||||
// Update a, b, and alpha based on the current guess for T
|
||||
updateMixingExpressions(T_new, aCalc, bCalc, aAlpha);
|
||||
// Calculate p using PR EoS
|
||||
double denom = mV * mV + 2 * mV * bCalc - bCalc * bCalc;
|
||||
double mV_b = mV - bCalc;
|
||||
double term2 = (aAlpha) / denom;
|
||||
p_iter = (GasConstant*T_new)/mV_b - term2;
|
||||
// Check if the result is within the specified tolerance
|
||||
double error =(p_iter-p)/p;
|
||||
if (fabs(error)<1e-10) {
|
||||
break;
|
||||
}
|
||||
m_dpdT = (GasConstant / mV_b - daAlpha_dT(T_new) / denom);
|
||||
T_new = T_new - (error/(m_dpdT/p));
|
||||
iteration++;
|
||||
}
|
||||
if (iteration==300)
|
||||
{
|
||||
throw CanteraError("PengRobinson::DP did not converge at",
|
||||
"negative temperature T = {} p= {} rho={} X1={} X2={}", T_new, p, rho,moleFractions_[0],moleFractions_[1]);
|
||||
}
|
||||
setDensity(rho);
|
||||
setTemperature(T_new);
|
||||
setState_TP(T_new,p);
|
||||
updateMixingExpressions();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -179,6 +179,36 @@ TEST_F(PengRobinson_Test, CoolPropValidate)
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(PengRobinson_Test, CoolPropValidateDP)
|
||||
{
|
||||
// Validate the P-R EoS in Cantera with P-R EoS from CoolProp
|
||||
|
||||
const double rhoCoolProp[10] = {
|
||||
9.067928191884574,
|
||||
8.318322900591179,
|
||||
7.6883521740498155,
|
||||
7.150504298001246,
|
||||
6.685330199667018,
|
||||
6.278630757480957,
|
||||
5.919763108091383,
|
||||
5.600572727499541,
|
||||
5.314694056926007,
|
||||
5.057077678380463
|
||||
};
|
||||
|
||||
double p = 5e5;
|
||||
|
||||
// Calculate Temperature using Peng-Robinson EoS from Cantera
|
||||
for(int i=0; i<10; i++)
|
||||
{
|
||||
const double tempReference = 300 + i*25;
|
||||
set_r(1.0);
|
||||
test_phase->setState_DP(rhoCoolProp[i], p,300);
|
||||
|
||||
EXPECT_NEAR(test_phase->temperature(),tempReference,1.e-3);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(PengRobinson, lookupSpeciesProperties)
|
||||
{
|
||||
AnyMap phase_def = AnyMap::fromYamlString(
|
||||
|
Loading…
Reference in New Issue
Block a user