Skip to content
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

Support calcuation of critical properties of mixtures in Modular Properties #1336

Merged
merged 16 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ Cubic equations of state require the following parameters to be defined:

1. `omega` (Pitzer acentricity factor) needs to be defined for each component (in the `parameter_data` for each component).
2. `kappa` (binary interaction parameters) needs to be defined for each component pair in the system. This parameter needs to be defined in the general `parameter_data` argument for the overall property package (as it can be used in multiple phases).
3. Component critical properties (`compress_fact_crit`, `dens_mol_crit`, `pressure_crit`, and `temperature_crit`) are often required as well.

Calculation of Properties
-------------------------
Expand All @@ -77,6 +78,26 @@ Many thermophysical properties are calculated using an ideal and residual term,

The residual term is derived from the partial derivatives of the cubic equation of state, whilst the ideal term is determined using pure component properties for the ideal gas phase defined for each component.

Critical Properties of Mixtures
-------------------------------

The critical properties of the mixture are calculated by solving the cubic equation of state at the critical point using the following constraints.

.. math:: \Omega_A R^2 T_c^2 = a_{c,m}P_c
.. math:: \Omega_BRT_c = b_{c,m}P_c
.. math:: 0 = Z_c^3 - (1+B_c-uB_c)Z_c^2 + (A_c-uB_c-(u-w)B_c^2)Z_c - A_cB_c-wB_c^2-wB_c^3
.. math:: P_c = Z_cRT_c\rho_{c}


with the following expressions:

.. math:: a_{c,j} = \frac{\Omega_AR^2T_{c,j}^2}{P_{c, j}}\alpha_j(T_c)
.. math:: a_{c,m} = \sum_i{\sum_j{y_iy_j(a_{c,i}a_{c,j})^{1/2}(1-\kappa_{ij})}}
.. math:: b_{c,m} = \sum_i{y_ib_i}
.. math:: A_c = \frac{a_{c,m}P_c}{R^2T_c^2}
.. math:: B_c = \frac{b_{c,m}P_c}{RT_c}


Mass Density by Phase
---------------------

Expand Down Expand Up @@ -109,14 +130,14 @@ Component Molar Enthalpy by Phase

Component molar enthalpies by phase are calculated using the pure component method provided by the users in the property package configuration arguments.

Molar Isobaric Heat Capcity (:math:`C_p`)
-----------------------------------------
Molar Isobaric Heat Capacity (:math:`C_p`)
------------------------------------------

The ideal molar isobaric heat capcity term is calculated from the weighted sum of the (ideal) component molar isobaric heat capacity:
The ideal molar isobaric heat capacity term is calculated from the weighted sum of the (ideal) component molar isobaric heat capacity:

.. math:: C_{p, ig}^0 = \sum_j y_j C_{p, ig, j}

The residual molar isobaric heat capcity term is given by:
The residual molar isobaric heat capacity term is given by:

.. math:: C_p^r = R \left[ T \left(\frac{\partial Z}{\partial T}\right)_P + Z - 1 \right] + \frac{ T \frac{d^2a_m}{dT^2}}{\sqrt{u^2 - 4w} \cdot b_m} \ln \left[ \frac{2Z + uB + \sqrt{u^2 - 4w} B}{2Z + uB - \sqrt{u^2 - 4w} B} \right]
.. math:: + \left(a_m - T \frac{da_m}{dT}\right) \cdot \frac{B}{b_m} \cdot \frac{\left(\frac{\partial Z}{\partial T}\right)_P + \frac{Z}{T}}{Z^2 + Z uB + wB^2}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ Introduction

Ideal behavior represents the simplest possible equation of state that ensures thermodynamic consistency between different properties.

Critical Properties of Mixtures
-------------------------------

The Ideal Equation of State module does not support the calculation of mixture critical properties as the ideal equation of state cannot represent the critical point.

Mass Density by Phase
---------------------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Equations of state (or equivalent methods) describe the relationship between dif

A wide range of equations of states are available in literature for different applications and levels of rigor, and the IDAES Generic Property Package Framework provides a number of prebuilt modules for users, which are listed below.

Equation of state packages may allow for user options (e.g. choosing a specific type of cubic equation of state). The options are set using the `equation_of_state_options` argument, and the options available are described in the documentation of each equation of state module.
Equation of state packages may allow for user options (e.g., choosing a specific type of cubic equation of state). The options are set using the `equation_of_state_options` argument, and the options available are described in the documentation of each equation of state module.

Equation of State Libraries
"""""""""""""""""""""""""""
Expand All @@ -44,6 +44,20 @@ Equation of State Libraries

eos/ideal
eos/cubic

Critical Properties of Mixtures
"""""""""""""""""""""""""""""""

Calculation of the critical properties of mixtures depends on the equation of state being used. As the Modular Property Package framework allows users to specify different equations of state for each phase, the following logic is used to determine which equation of state to use for calculating critical properties.

1. If a vapor-liquid equilibrium pair is defined in the `"phases_in_equilibrium"` configuration argument, then the liquid phase from this pair is used (IDAES generally assumed supercritical fluids are liquid like).
andrewlee94 marked this conversation as resolved.
Show resolved Hide resolved
2. If no vapor-liquid equilibrium pair is defined, then the first liquid phase define is used.
andrewlee94 marked this conversation as resolved.
Show resolved Hide resolved
3. If no liquid phases are defined then the vapor phase is used (it is assumed there will only be one vapor phase).
4. If no vapor phase is defined, then a `PropertyPackageError` is returned as there is no suitable phase for calculating critical properties.

Note that not all Equations of State are suitable for calculating critical properties as many cannot represent the critical conditions. The Ideal equation of State is one common example of an equation of state that DOES NOT support critical properties.

During initialization, the critical properties of the mixture are approximated using the mole fraction weighted sum of the component critical properties (note that users must provide values for all component critical properties (i.e., `compress_fact_crit`, `dens_mol_crit`, `pressure_crit` and `temperature_crit`) for initialization if critical properties are to be calculated.
andrewlee94 marked this conversation as resolved.
Show resolved Hide resolved

Phase-Specific Parameter
^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -53,6 +67,6 @@ In some cases, a property package may include parameters which are specific to a
Phases with Partial Component Lists
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

In many applications a mixture will contain species that only appear in a single phase (either by nature or assumption). Common examples include crystalline solids and non-condensable gases. The IDAES Generic Property Package Framework provides support for these behaviors and allows users to specify phase-specific component lists (i.e. a list of components which appear in a given phase).
In many applications a mixture will contain species that only appear in a single phase (either by nature or assumption). Common examples include crystalline solids and non-condensable gases. The IDAES Generic Property Package Framework provides support for these behaviors and allows users to specify phase-specific component lists (i.e., a list of components which appear in a given phase).

This is done by providing a phase with a `component_list` argument, which provides a `list` of component names which appear in the phase. The framework automatically validates the `component_list` argument to ensure that it is a sub-set of the master component list for the property package, and will inform the user if an unrecognized component is included. If a phase is not provided with a `component_list` argument it is assumed that all components defined in the master component list may be present in the phase.
1 change: 1 addition & 0 deletions idaes/core/base/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ def build(self):

# Create Vars for common parameters
var_dict = {
"compress_fact_crit": pyunits.dimensionless,
"dens_mol_crit": base_units.DENSITY_MOLE,
"omega": pyunits.dimensionless,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be nice to one day rename this "acentric factor", but that can wait for another day.

"pressure_crit": base_units.PRESSURE,
Expand Down
13 changes: 12 additions & 1 deletion idaes/core/base/property_meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,9 +257,20 @@
return self._length**3

@property
def MOLAR_VOLUME(self):
def VOLUME_MASS(self):
return self._length**3 * self._mass**-1

@property
def VOLUME_MOLE(self):
return self._length**3 * self._amount**-1

# Backward compatibility name
@property
def MOLAR_VOLUME(self):
msg = "The unit name MOLAR_VOLUME is being deprecated in favor of VOLUME_MOL."
deprecation_warning(msg=msg, logger=_log, version="2.3.0", remove_in="3.0.0")
return self.VOLUME_MOLE

Check warning on line 272 in idaes/core/base/property_meta.py

View check run for this annotation

Codecov / codecov/patch

idaes/core/base/property_meta.py#L270-L272

Added lines #L270 - L272 were not covered by tests

# Flows
@property
def FLOW_MASS(self):
Expand Down
9 changes: 7 additions & 2 deletions idaes/core/base/property_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,11 @@ class StandardPropertySet(PropertySetBase):
doc="Compressiblity Factor",
units=pyunits.dimensionless,
)
compress_fact_crit = PropertyMetadata(
name="compress_fact_crit",
doc="Compressiblity Factor at Critical Point",
units=pyunits.dimensionless,
)
conc_mass = PropertyMetadata(
name="conc_mass",
doc="Concentration on a Mass Basis",
Expand Down Expand Up @@ -890,12 +895,12 @@ class StandardPropertySet(PropertySetBase):
vol_mol = PropertyMetadata(
name="vol_mol",
doc="Molar Volume",
units="MOLAR_VOLUME",
units="VOLUME_MOLE",
)
vol_mol_crit = PropertyMetadata(
name="vol_mol",
doc="Molar Volume at Critical Point",
units="MOLAR_VOLUME",
units="VOLUME_MOLE",
)
# Log terms
log_act = PropertyMetadata(
Expand Down
8 changes: 8 additions & 0 deletions idaes/core/base/tests/test_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ def get_metadata(self):
m.comp = Component(
parameter_data={
"mw": 10,
"compress_fact_crit": 1,
"dens_mol_crit": 55,
"pressure_crit": 1e5,
"temperature_crit": 500,
Comment on lines +188 to 191
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good example of the perils of inconsistent data. We say Z_crit = 1, but P_crit/(rho_mol_critRT_crit) ~= 0.4376. It probably doesn't matter for this test, though.

}
Expand All @@ -193,6 +195,12 @@ def get_metadata(self):
assert isinstance(m.comp.mw, Param)
assert m.comp.mw.value == 10

assert isinstance(m.comp.compress_fact_crit, Var)
assert m.comp.compress_fact_crit.value == 1

assert isinstance(m.comp.dens_mol_crit, Var)
assert m.comp.dens_mol_crit.value == 55

assert isinstance(m.comp.pressure_crit, Var)
assert m.comp.pressure_crit.value == 1e5

Expand Down
2 changes: 2 additions & 0 deletions idaes/core/base/tests/test_property_meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ def test_luminous_intensity(unit_set):
derived_quantities = {
"area": units.m**2,
"volume": units.m**3,
"volume_mass": units.m**3 / units.kg,
"volume_mole": units.m**3 / units.mol,
"flow_mass": units.kg * units.s**-1,
"flow_mole": units.mol * units.s**-1,
"flow_vol": units.m**3 * units.s**-1,
Expand Down
Loading
Loading