{
"cells": [
{
"cell_type": "markdown",
"id": "fbc5e807",
"metadata": {},
"source": [
"## Generic Cubic Equation of State"
]
},
{
"cell_type": "markdown",
"id": "acfb71d5",
"metadata": {},
"source": [
"Our Cubic Equations of State are implemented based on the generic Cubic\n",
"Equation:\n",
"\n",
"$$\n",
" P = \\frac{RT}{V-b} - \\frac{a_c\\alpha(T_r)}{(V + \\delta_1 b)(V - \\delta_2 b)}\n",
"$$\n",
"\n",
"Almost all cubic equations of state use the Quadratic mixing rule with all its\n",
"parameters set to zero by default. Check the \"Mixing Rules\" section of the\n",
"Cubic Equations of State tutorial for more information about different mixing\n",
"rules and how to change them.\n",
"\n",
"Here we give a minimum example of how to set all the parameters of the\n",
"available cubic equations of state. Check out for all the sections of the\n",
"\"Equations of State (EoS)\" tutorial to learn all you can do with the Cubic\n",
"Equations of State."
]
},
{
"cell_type": "markdown",
"id": "f06041b8",
"metadata": {},
"source": [
"## Peng-Robinson (1976)\n",
"\n",
"The Peng-Robinson (1976) EoS uses the following $\\alpha$ function and\n",
"correlation for $k$.\n",
"\n",
"$$ \\alpha(T_r) = \\left(1 + k (1 - \\sqrt{T_r})\\right)^2 $$\n",
"$$ k = 0.37464 + 1.54226 \\, \\omega - 0.26993 \\, \\omega^2 $$\n",
"$$ a_c = 0.45723553 \\frac{R^2 T_c^2}{P_c} $$\n",
"$$ b = 0.07779607 \\frac{R T_c}{P_c} $$\n",
"$$ \\delta_1 = 1 + \\sqrt{2} $$\n",
"$$ \\delta_2 = 1 - \\sqrt{2} $$"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "bd24c0cb",
"metadata": {},
"outputs": [],
"source": [
"import yaeos\n",
"\n",
"\n",
"Tcs = [190.564, 617.7] # Critical temperatures [K]\n",
"Pcs = [45.99, 21.1] # Critical pressures [bar]\n",
"ws = [0.0115478, 0.492328] # Acentric factors [-]\n",
"\n",
"\n",
"# Setting a Peng-Robinson 1976 cubic equation of state\n",
"# By default, the Quadratic mixing rule is used with all parameters set to zero\n",
"model_pr76 = yaeos.PengRobinson76(\n",
" critical_temperatures=Tcs,\n",
" critical_pressures=Pcs,\n",
" acentric_factors=ws\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "8ef8f7f1",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1.739232789370789"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"n = [10.0, 5.0] # Moles vector [mol]\n",
"T = 303.15 # Temperature [K]\n",
"P = 10.0 # Pressure [bar]\n",
"\n",
"\n",
"# Calculate a stable volume root [L]\n",
"model_pr76.volume(n, P, T, root=\"stable\")"
]
},
{
"cell_type": "markdown",
"id": "b7a268ca",
"metadata": {},
"source": [
"## Peng-Robinson (1978)\n",
"\n",
"The Peng-Robinson (1978) EoS is an improved version of the original\n",
"Peng-Robinson (1976) equation for heavier components. This equation ensures a\n",
"monotonically increasing $k$ as the values of $\\omega$ increases. It uses\n",
"the following $\\alpha$ function and correlation for $k$.\n",
"\n",
"$$ \\alpha(T_r) = \\left(1 + k (1 - \\sqrt{T_r})\\right)^2 $$\n",
"\n",
"$$\n",
"k =\n",
"\\begin{cases} \n",
"0.37464 + 1.54226 \\, \\omega - 0.26992 \\, \\omega^2 & \\text{if} \\quad \\omega \\leq 0.491 \\\\\n",
"0.37464 + 1.48503 \\, \\omega - 0.16442 \\, \\omega^2 + 0.016666 \\, \\omega^3 & \\text{if} \\quad \\omega > 0.491\n",
"\\end{cases}\n",
"$$\n",
"\n",
"$$ a_c = 0.45723553 \\frac{R^2 T_c^2}{P_c} $$\n",
"$$ b = 0.07779607 \\frac{R T_c}{P_c} $$\n",
"$$ \\delta_1 = 1 + \\sqrt{2} $$\n",
"$$ \\delta_2 = 1 - \\sqrt{2} $$"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "b3bc4ddd",
"metadata": {},
"outputs": [],
"source": [
"import yaeos\n",
"\n",
"\n",
"Tcs = [190.564, 617.7] # Critical temperatures [K]\n",
"Pcs = [45.99, 21.1] # Critical pressures [bar]\n",
"ws = [0.0115478, 0.492328] # Acentric factors [-]\n",
"\n",
"\n",
"# Setting a Peng-Robinson 1978 cubic equation of state\n",
"# By default, the Quadratic mixing rule is used with all parameters set to zero\n",
"model_pr78 = yaeos.PengRobinson78(\n",
" critical_temperatures=Tcs,\n",
" critical_pressures=Pcs,\n",
" acentric_factors=ws\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "465bb60f",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1.7375354121831335"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"n = [10.0, 5.0] # Moles vector [mol]\n",
"T = 303.15 # Temperature [K]\n",
"P = 10.0 # Pressure [bar]\n",
"\n",
"\n",
"# Calculate a stable volume root [L]\n",
"model_pr78.volume(n, P, T, root=\"stable\")"
]
},
{
"cell_type": "markdown",
"id": "83ea1d43",
"metadata": {},
"source": [
"## Soave-Redlich-Kwong\n",
"\n",
"The Soave-Redlich-Kwong EoS uses the following $\\alpha$ function and its\n",
"respective correlation for $k$.\n",
"\n",
"$$ \\alpha(T_r) = (1 + k (1 - \\sqrt{T_r}))^2 $$\n",
"$$ k = 0.48 + 1.574 \\omega - 0.175 \\omega^2 $$\n",
"$$ a_c = 0.427480 \\frac{R^2 T_c^2}{P_c} $$\n",
"$$ b_c = 0.086640 \\frac{R T_c}{P_c} $$\n",
"$$ \\delta_1 = 1 $$\n",
"$$ \\delta_2 = 0 $$"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "69ee5ab6",
"metadata": {},
"outputs": [],
"source": [
"import yaeos\n",
"\n",
"\n",
"Tcs = [190.564, 617.7] # Critical temperatures [K]\n",
"Pcs = [45.99, 21.1] # Critical pressures [bar]\n",
"ws = [0.0115478, 0.492328] # Acentric factors [-]\n",
"\n",
"\n",
"# Setting a Soave-Redlich-Kwong cubic equation of state\n",
"# By default, the Quadratic mixing rule is used with all parameters set to zero\n",
"model_srk = yaeos.SoaveRedlichKwong(\n",
" critical_temperatures=Tcs,\n",
" critical_pressures=Pcs,\n",
" acentric_factors=ws\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "a38d8d6a",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1.7375354121831335"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"n = [10.0, 5.0] # Moles vector [mol]\n",
"T = 303.15 # Temperature [K]\n",
"P = 10.0 # Pressure [bar]\n",
"\n",
"\n",
"# Calculate a stable volume root [L]\n",
"model_pr78.volume(n, P, T, root=\"stable\")"
]
},
{
"cell_type": "markdown",
"id": "76c32e5d",
"metadata": {},
"source": [
"## RKPR\n",
"\n",
"The RKPR EoS extends the classical formulation of Cubic Equations of State by\n",
"freeing the parameter $\\delta_1$ and setting $\\delta_2 =\n",
"\\frac{1+\\delta_1}{1-\\delta_1}$. This extra degree provides extra ways of\n",
"implementing the equation in comparison of other Cubic EoS (like Peng-Robinson\n",
"and Soave-Redlich-Kwong) which are limited to definition of their critical\n",
"constants.\n",
"\n",
"Besides that extra parameter, the RKPR includes another $\\alpha$\n",
"function:\n",
"\n",
"$$\n",
" \\alpha(T_r) = \\left(\\frac{3}{2+T_r}\\right)^k\n",
"$$\n",
"\n",
"These two extra parameters can be provided as arguments. But, if they are\n",
"not provided they will be calculated by the following correlations:\n",
"\n",
"$$ \\delta_1 = d_1 + d_2 (d_3 - Z_c)^d_4 + d_5 (d_3 - Z_c) ^ {d_6} $$\n",
"$$ k = (A_1 Z_c + A_0)\\omega^2 + (B_1 Z_c + B_0)\\omega + (C_1 Z_c + C{_0)} $$\n",
"\n",
"In this implementation, the $k$ constants (if not provided) will also \n",
"be readjusted to assure that $\\omega = -log_{10}\\left(P_r^{sat}\\right) - 1$ \n",
"at $T_r = 0.7$.\n",
"\n",
"It is also possible to include the parameters as optional arguments."
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "ce9ce59d",
"metadata": {},
"outputs": [],
"source": [
"import yaeos\n",
"\n",
"import numpy as np\n",
"\n",
"Tcs = np.array([190.564, 617.7]) # Critical temperatures [K]\n",
"Pcs = np.array([45.99, 21.1]) # Critical pressures [bar]\n",
"Vcs = np.array([0.0986, 0.625]) # Critical volumes [L/mol]\n",
"\n",
"ws = [0.0115478, 0.492328] # Acentric factors [-]\n",
"\n",
"R = 0.08314462618 # Gas constant [L bar / (K mol)]\n",
"\n",
"\n",
"# From critical properties we can calculate the critical compressibility factors\n",
"Zcs = Pcs * Vcs / (R * Tcs)\n",
"\n",
"\n",
"# Setting a RKPR cubic equation of state\n",
"# By default, the Quadratic mixing rule is used with all parameters set to zero\n",
"model_rkpr = yaeos.RKPR(\n",
" critical_temperatures=Tcs,\n",
" critical_pressures=Pcs,\n",
" acentric_factors=ws,\n",
" critical_z=Zcs\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "ba2a1e6e",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1.684743540150981"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"n = [10.0, 5.0] # Moles vector [mol]\n",
"T = 303.15 # Temperature [K]\n",
"P = 10.0 # Pressure [bar]\n",
"\n",
"\n",
"# Calculate a stable volume root [L]\n",
"model_rkpr.volume(n, P, T, root=\"stable\")"
]
},
{
"cell_type": "markdown",
"id": "63de3f4e",
"metadata": {},
"source": [
"## Predictive Soave-Redlich-Kwong (PSRK)\n",
"\n",
"The $\\alpha$ function of the PSRK EoS is the Mathias-Copeman alpha function:\n",
"\n",
"$$\n",
"\\alpha_i(T_r) = \\left[1+c_{1, i}\\left(1-\\sqrt{T_{r, i}}\\right)+c_{2,\n",
"i}\\left(1-\\sqrt{T_{r, i}}\\right)^2 + c_{3,i}\\left(1-\\sqrt{T_{r,\n",
"i}}\\right)^3\\right]^2\n",
"$$\n",
"\n",
"The $c_{1,i}$, $c_{2,i}$, and $c_{3,i}$ parameters are specific to each component and are determined from vapor pressure experimental data. If not provided, the PSRK EOS will use the same $\\alpha$ as the Soave-Redlich-Kwong EoS.\n",
"\n",
"\n",
"The mixing rule is the modified Huron-Vidal mixing rule (MHV) with $u=1.1$:\n",
"\n",
"$$\n",
"\\frac{a(T)}{b R T}=\\sum x_i \\frac{a_{i i}(T)}{b_i R T}+\\frac{\\frac{G_0^{\\mathrm{E}}}{R T}+\\sum x_i \\ln \\frac{b}{b_i}}{\\ln \\frac{u}{u+1}}\n",
"$$\n",
"\n",
"$$\n",
"b = \\sum_i x_i b_i\n",
"$$\n",
"\n",
"As shown, the MHV mixing rule is dependent of excess Gibbs free energy the $G_0^{\\mathrm{E}}$. This is calculated from the PSRK-UNIFAC model. For that the functional groups of each molecule must be provided.\n",
"\n",
"Checkout the Fortran side documentation of the PSRK-UNIFAC model to check the functional groups available:\n",
"\n",
"https://ipqa-research.github.io/yaeos/page/index.html\n",
"\n",
"Groups are assigned as dictionaries. For example, n-hexane has two \"CH3\" groups and four \"CH2\" groups. The subgroups id of \"CH3\" and \"CH2\" are 1 and 2, respectively. So, the functional groups of n-hexane must be defined as:\n",
"\n",
"```python\n",
"n_hexane_groups = {1: 2, 2: 4}\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "efc8853f",
"metadata": {},
"outputs": [],
"source": [
"import yaeos\n",
"\n",
"\n",
"# methane - n-decane\n",
"Tcs = [190.564, 617.7] # Critical temperatures [K]\n",
"Pcs = [45.99, 21.1] # Critical pressures [bar]\n",
"ws = [0.0115478, 0.492328] # Acentric factors [-]\n",
"\n",
"# Mathias-Copeman alpha parameters\n",
"c1 = [0.49258, 1.2407]\n",
"c2 = [0.0, -0.34943]\n",
"c3 = [0.0, 0.7327]\n",
"\n",
"# Functional groups of PSRK-UNIFAC\n",
"groups = [{118: 1}, {1: 2, 2: 8}]\n",
"\n",
"\n",
"model_psrk = yaeos.PSRK(\n",
" critical_temperatures=Tcs,\n",
" critical_pressures=Pcs,\n",
" acentric_factors=ws,\n",
" molecules=groups,\n",
" c1=c1,\n",
" c2=c2,\n",
" c3=c3\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "0c2d18ce",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1.9855806068142714"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"n = [10.0, 5.0] # Moles vector [mol]\n",
"T = 303.15 # Temperature [K]\n",
"P = 10.0 # Pressure [bar]\n",
"\n",
"\n",
"# Calculate a stable volume root [L]\n",
"model_psrk.volume(n, P, T, root=\"stable\")"
]
},
{
"cell_type": "markdown",
"id": "23e2079b",
"metadata": {},
"source": [
"### Using `ugropy` to retrieve PSRK functional groups\n",
"\n",
"Our research group has another Python package called `ugropy`\n",
"\n",
"https://github.com/ipqa-research/ugropy\n",
"\n",
"That package can be used to retrieve the functional groups of a molecule by its\n",
"SMILES, or name. Here it's a little example of how to use it. Please refer\n",
"to the `ugropy` documentation for more information.\n",
"\n",
"The package can be installed with:\n",
"\n",
"```bash\n",
"pip install ugropy\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": 22,
"id": "e0d3a9ad",
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import ugropy as ug\n",
"\n",
"# Obtain the functional groups of the PSRK model\n",
"methane_groups = ug.psrk.get_groups(\"methane\")\n",
"\n",
"decane_groups = ug.psrk.get_groups(\"decane\")\n",
"\n",
"# Visualize the functional groups:\n",
"methane_groups.draw()"
]
},
{
"cell_type": "code",
"execution_count": 23,
"id": "2149c064",
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"decane_groups.draw()"
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "9444ff18",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[{118: 1}, {1: 2, 2: 8}]\n"
]
}
],
"source": [
"# Get the functional groups list ready to use in yaeos PSRK!\n",
"\n",
"groups = [methane_groups.subgroups_num, decane_groups.subgroups_num]\n",
"\n",
"print(groups)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "yaeos",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.12"
}
},
"nbformat": 4,
"nbformat_minor": 5
}