Week 3: Volumetric Behaviour of Pure Fluids from Intermolecular Interactions#

Second order coefficient of the virial expansion from molecular-level information.#

Consider a single component molecular systems interacting via the interatomic potential \(\Gamma_{ii}\):

The second order virial coefficient can be written as a function of the intermolecular potential as:

\[ B_{ii}=2\pi{N_A}\int_0^\infty(1-\exp(-\Gamma_{ii}/RT))r^2)dr \]

Let’s compute the second virial coefficient for a series of monocomponent gases.

Two body interaction potential#

import matplotlib.pyplot as plt 
from matplotlib import cm
import numpy as np

figure=plt.figure()
axes = figure.add_axes([0.1,0.1,1.5,1.5])
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)
axes.set_xlabel('r, A', fontsize=16);
axes.set_ylabel('$\Gamma$, [K]',fontsize=16);
axes.set_xlim([0.5,20]);
axes.set_ylim([-250,50]);

#Intermolecular Potential, i.e. LJ 6/12
#Species=[Ar, Kr, Xe, CH4, N2, C2H4, C2H6, C3H8]
SIGMA=[3.499, 3.846, 4.100, 4.010, 3.694, 4.433, 5.220, 5.711] # Angstrom
EPS=[118.13, 162.74, 222.32, 142.87, 96.26, 202.52, 194.14, 233.28] #K 
a=[0.121, 0.144, 0.173, 0.283, 0.250, 0.249, 0.359, 0.470] #Note: C2H4 is not in Table 5.3 of Prausnitz

r = np.linspace(0.3, 25, 500)
Gamma=np.zeros((np.size(r),np.size(SIGMA)))
Gamma_2=np.zeros((np.size(r),np.size(SIGMA)))

color=iter(cm.gist_gray(np.linspace(0,1,np.size(SIGMA)+1)))
color_2=iter(cm.gist_heat(np.linspace(0,1,np.size(SIGMA)+1)))

# Consider a LJ gas
for i in np.arange(0,np.size(SIGMA)):
    c=next(color)
    sr6=np.power(np.divide(SIGMA[i],r),6)
    Gamma[:,i]=4*EPS[i]*(np.power(sr6,2)-sr6)
    axes.plot(r,Gamma[:,i], marker=' ' , c=c, linewidth=3.0);

## Consider a Kihara gas
#for i in np.arange(0,np.size(SIGMA)):
##    c_2=next(color_2)
#    sr6_2=np.power(np.divide(SIGMA[i]-2*a[i],r-2*a[i]),6)
#    Gamma_2[:,i]=4*EPS[i]*(np.power(sr6_2,2)-sr6_2)
#    axes.plot(r,Gamma_2[:,i], marker=' ' , c=c_2, linewidth=3.0);
_images/84cfa824724aa07066f88e50e92b55e4abc7902ac73f35a901f009dd539a1f26.png
# Compute the second Virial coefficient as a function of T
Temperature = np.linspace(300, 500, 50)
figure=plt.figure()
axes = figure.add_axes([0.1,0.1,1.5,1.5])
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)

axes.set_xlabel('Temperature, [K]', fontsize=14);
axes.set_ylabel('B, dm$^3$ mol$^{-1}$',fontsize=14);

B=np.zeros((np.size(Temperature),np.size(SIGMA)))
B_2=np.zeros((np.size(Temperature),np.size(SIGMA)))

color=iter(cm.gist_gray(np.linspace(0,1,np.size(SIGMA)+1)))
color_2=iter(cm.gist_heat(np.linspace(0,1,np.size(SIGMA)+1)))

# Consider a LJ gas
for i in np.arange(0,np.size(SIGMA)):
    c=next(color)
    for j in np.arange(0,np.size(Temperature)):
        B[j,i]=2*np.pi*6E23*np.trapz((1-np.exp(-Gamma[:,i]/Temperature[j]))*np.power(r*1E-9,2),r*1E-9)
    axes.plot(Temperature,B[:,i], marker=' ' , c=c, linewidth=3.0);

# Consider a Kihara gas    
#for i in np.arange(0,np.size(SIGMA)):
#    c_2=next(color_2)
#    for j in np.arange(0,np.size(Temperature)):
#        B_2[j,i]=2*np.pi*6E23*np.trapz((1-np.exp(-Gamma_2[:,i]/Temperature[j]))*np.power(r*1E-9,2),r*1E-9)
#    axes.plot(Temperature,B_2[:,i], marker=' ' , c=c_2, linewidth=3.0);
_images/8822ead9417017108559ed70b326425c1052c19bba6dc803504f104d0cb737bb.png

Properties#

import numpy as np
from matplotlib import cm
import matplotlib.pyplot as plt 
from mpl_toolkits.mplot3d import Axes3D 
###
##Choose Chemical Specie:
#Species=[Ar, Kr, Xe, CH4, N2, C2H4, C2H6, C3H8]
Chem_Sp=3
# Note: I attach as an example Ar since it is important to note that Michels' 
# highly accurate second-virial-coefficient data for Ar can not be represented 
# over a large temperature range by the LJ potential using only one set of potential
# parameters. However, these same data can be represented within the very small
# experimental error by the Kihara potential using only one set of parameters.
# For a further discussion on this refer to Praustnitz recommented textbook.
###

Compressibility factor#

## Z Diagram
rho=np.linspace(1, 15, 100) # mol / l

rho_g, Temperature_g = np.meshgrid(rho, Temperature) 

Z=np.zeros((np.shape(rho_g)))
Z_2=np.zeros((np.shape(rho_g)))

# For a LJ gas
for i in np.arange(0,np.size(rho)):
    Z[:,i]=1+rho_g[:,i]*B[:,Chem_Sp]

# For a Kihara gas
for i in np.arange(0,np.size(rho)):
    Z_2[:,i]=1+rho_g[:,i]*B_2[:,Chem_Sp]


figure=plt.figure(figsize=(10, 8))
axes = figure.add_subplot(projection ='3d')

plt.xticks(fontsize=14)
plt.yticks(fontsize=14)

# For a LJ gas
surf=axes.plot_surface(rho_g,Temperature_g,Z,cmap=cm.coolwarm,
                       linewidth=0, antialiased=False,alpha=0.5)

# For a Kihara gas
surf_2=axes.plot_surface(rho_g,Temperature_g,Z_2,cmap=cm.Spectral,
                        linewidth=0, antialiased=False,alpha=0.5)

axes.set_xlabel('molar density', fontsize=14, labelpad=10);
axes.set_ylabel('Temperature',fontsize=14, labelpad=10);
axes.set_zlabel('Z, [-]',fontsize=14, labelpad=10);
for t in axes.zaxis.get_major_ticks(): t.label.set_fontsize(14)
figure.colorbar(surf, shrink=0.5, aspect=10, pad=0);
figure.colorbar(surf_2, shrink=0.5, aspect=10, pad=0.15);

figure=plt.figure()
axes = figure.add_axes([0.1,0.1,1.5,1.5])
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)
axes.set_xlabel('molar volume, [l mol$^{-1}$]', fontsize=14, labelpad=10);
axes.set_ylabel('Z, [-]',fontsize=14,labelpad=10);

color=iter(cm.coolwarm(np.linspace(0,1,np.size(Temperature)+1)))
color_2=iter(cm.Spectral(np.linspace(0,1,np.size(Temperature)+1)))

# For a LJ gas
for i in np.arange(0,np.size(Temperature)):
        c=next(color)
        axes.plot(1/rho,Z[i,:], marker=' ' , c=c);
figure.colorbar(surf, shrink=0.85, aspect=10);

# For a Kihara gas
#for i in np.arange(0,np.size(Temperature)):
#        c_2=next(color_2)
#        axes.plot(1/rho,Z_2[i,:], marker=' ' , c=c_2);
#figure.colorbar(surf_2, shrink=0.85, aspect=10);
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[4], line 35
     33 axes.set_ylabel('Temperature',fontsize=14, labelpad=10);
     34 axes.set_zlabel('Z, [-]',fontsize=14, labelpad=10);
---> 35 for t in axes.zaxis.get_major_ticks(): t.label.set_fontsize(14)
     36 figure.colorbar(surf, shrink=0.5, aspect=10, pad=0);
     37 figure.colorbar(surf_2, shrink=0.5, aspect=10, pad=0.15);

AttributeError: 'XTick' object has no attribute 'label'
_images/abbe4bfa2b18704040be000ebc9a2415514ccc7428428b963db4cca7bc32943a.png

P/v isotherms Diagram#

rho=np.linspace(1, 10, 50) # mol / l

rho_g, Temperature_g = np.meshgrid(rho, Temperature)

P=np.zeros((np.shape(rho_g)))
P_2=np.zeros((np.shape(rho_g)))

R=0.082;

# For a LJ gas
for i in np.arange(0,np.size(rho)):
    P[:,i]=Temperature_g[:,i]*R*rho_g[:,i]+Temperature_g[:,i]*R*rho_g[:,i]*rho_g[:,i]*B[:,Chem_Sp]

# For a Kihara gas
for i in np.arange(0,np.size(rho)):
    P_2[:,i]=Temperature_g[:,i]*R*rho_g[:,i]+Temperature_g[:,i]*R*rho_g[:,i]*rho_g[:,i]*B_2[:,Chem_Sp]

figure=plt.figure(figsize=(10, 8))
#axes = figure.add_axes([0.1,0.1,0.1,1.2,1.2,1.2])
axes = figure.add_subplot(projection ='3d') 

plt.xticks(fontsize=14)
plt.yticks(fontsize=14)

# For a LJ gas
surf=axes.plot_surface(1/rho_g,Temperature_g,P,cmap=cm.coolwarm,
                       linewidth=0, antialiased=False,alpha=0.5)

# For a Kihara gas
surf_2=axes.plot_surface(1/rho_g,Temperature_g,P_2,cmap=cm.Spectral,
                       linewidth=0, antialiased=False,alpha=0.5)

axes.set_xlabel('molar volume', fontsize=14, labelpad=10);
axes.set_ylabel('Temperature',fontsize=14, labelpad=10);
axes.set_zlabel('Pressure',fontsize=14, labelpad=10);
for t in axes.zaxis.get_major_ticks(): t.label.set_fontsize(14)
figure.colorbar(surf, shrink=0.5, aspect=10, pad = 0);
figure.colorbar(surf_2, shrink=0.5, aspect=10, pad=0.15);

figure=plt.figure()
axes = figure.add_axes([0.1,0.1,1.5,1.5])
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)
axes.set_xlabel('molar volume, [l mol$^{-1}$]', fontsize=14);
axes.set_ylabel('P, [atm]',fontsize=14);

color=iter(cm.coolwarm(np.linspace(0,1,np.size(Temperature)+1)))
#color_2=iter(cm.Spectral(np.linspace(0,1,np.size(Temperature)+1)))

# For a LJ gas
for i in np.arange(0,np.size(Temperature)):
        c=next(color)
        axes.plot(1/rho,P[i,:], marker=' ' , c=c);

# For a Kihara gas
#for i in np.arange(0,np.size(Temperature)):
#        c_2=next(color_2)
#        axes.plot(1/rho,P_2[i,:], marker=' ' , c=c_2);

axes.set_ylim([0,200]);
figure.colorbar(surf, shrink=0.85, aspect=10);
#figure.colorbar(surf_2, shrink=0.85, aspect=10);
_images/4b973b67544c6bd26a5e48efee1a2a8dac18a8516f9356cdaf452b9298ccc69d.png _images/cf6a7c0e5842b324b3548e2db7ffb0c29a132ffc0ff34f096b79838cf4c4ad6d.png