Imagine an experiment in which a liquid mixture of known composition is slowly heated under constant pressure. The bubble point temperature is reached when the first bubble of vapor appears. This is the temperature at which a mixture begins to boil.
Next, imagine an experiment in which the pressure is lowered for a liquid mixture of known composition. The temperature is held constant. In this case the bubble point pressure is reach when the first bubble appears.
In each case, the composition $y_n, n = 1,2,\ldots,N$ of the bubble is given by
$$ y_n = x_n \frac{P^{sat}_n(T)}{P}$$which, at the bubble point, must satisfy the condition
$$ \sum_{n=1}^N x_n \frac{P^{sat}_n(T)}{P} = 1$$Initialize the IPython workspace with pylab and set useful plotting defaults useful for presentations.
%pylab inline
pylab.rcParams['figure.figsize'] = (10,4)
pylab.rcParams['font.size'] = 12
pylab.rcParams['lines.linewidth'] = 1.6
Alternatively, solving for $x_n$, then summing gives the dew point calculation
$$ x_n = y_n \frac{P}{P^{sat}_n(T)}\qquad \implies \qquad \sum_{n=1}^N y_n \frac{P}{P^{sat}_n(T)} = 1$$For binary mixtures $x_B = 1-x_A$
$$ x_A\left( P^{sat}_A(T) - P^{sat}_B(T)\right) = P - P^{sat}_B(T) $$which gives
$$ x_A = \frac{P - P^{sat}_B(T)}{P^{sat}_A(T) - P^{sat}_B(T)} \qquad x_B = \frac{P^{sat}_A - P}{P^{sat}_A(T) - P^{sat}_B(T)}$$$$ y_A = x_A\frac{P^{sat}_A(T)}{P} \qquad\quad\quad\quad y_B = x_B\frac{P^{sat}_B(T)}{P}$$from scipy.optimize import brentq as fzero
A = 'methanol'
B = 'water'
def Tbub(P,xA):
fbub = lambda T: xA*Psat[A](T)/P + (1-xA)*Psat[B](T)/P - 1
return fzero(fbub,0.99*Tsat[A](P),1.01*Tsat[B](P))
def Tdew(P,yA):
fdew = lambda T:yA*P/Psat[A](T) + (1-yA)*P/Psat[B](T) - 1
return fzero(fdew,0.99*Tsat[A](P),1.01*Tsat[B](P))
x = linspace(0,1)
plot(x,map(lambda x: Tbub(760,x),x))
plot(x,map(lambda x: Tdew(760,x),x))
xlabel('x,y ' + A)
ylabel('Temperature $^{\circ}C$')
title('Txy Diagram: ' + A + "/" + B)
legend(['Bubble','Dew'],'best')
grid()
Raoult's law work
A = 'methanol'
B = 'benzene'
Txy = array([\
[70.67, 0.026, 0.267],\
[66.44, 0.050, 0.371],\
[62.87, 0.088, 0.457],\
])
Txy = array([\
[351.76, 0.00200, 0.04100],\
[350.80, 0.00280, 0.06600],\
[350.67, 0.00300, 0.06840],\
[350.43, 0.00300, 0.08120],\
[350.37, 0.00410, 0.08200],\
[349.20, 0.00550, 0.11720],\
[348.45, 0.00580, 0.13860],\
[346.92, 0.01340, 0.19240],\
[346.21, 0.01900, 0.20600],\
[344.11, 0.02760, 0.26580],\
[341.10, 0.04600, 0.33920],\
[340.90, 0.04800, 0.34400],\
[337.17, 0.08300, 0.43000],\
[334.23, 0.14370, 0.49980],\
[334.19, 0.17000, 0.51800],\
[333.07, 0.18580, 0.52120],\
[332.55, 0.27600, 0.54420],\
[331.58, 0.36400, 0.57360],\
[331.30, 0.45580, 0.58700],\
[331.19, 0.52400, 0.59810],\
[331.12, 0.59700, 0.61140],\
[331.12, 0.63700, 0.62000],\
[331.13, 0.67390, 0.62900],\
[331.14, 0.68000, 0.63220],\
[331.20, 0.70240, 0.64080],\
[331.21, 0.70710, 0.64160],\
[331.28, 0.72980, 0.65090],\
[331.37, 0.74400, 0.65310],\
[331.60, 0.77680, 0.66910],\
[331.80, 0.80310, 0.68380],\
[332.14, 0.83800, 0.70900],\
[332.75, 0.87540, 0.74800],\
[333.33, 0.89980, 0.77420],\
[333.75, 0.91780, 0.80020],\
[334.05, 0.92500, 0.81180],\
[334.79, 0.94240, 0.85100],\
[335.75, 0.96520, 0.89980],\
[336.72, 0.98490, 0.94920],\
[336.87, 0.98800, 0.95720],\
[336.93, 0.98900, 0.96100],\
[337.10, 0.99180, 0.96840],\
[337.36, 0.99490, 0.97990]])
P = 760
T = linspace(Tsat[A](P),Tsat[B](P))
x = map(lambda T: (P - Psat[B](T))/(Psat[A](T)-Psat[B](T)), T)
y = map(lambda T: xA(T)*Psat[A](T)/P, T)
figure(figsize=(6,6))
plot(x,y)
plot(Txy.T[1],Txy.T[2],'r',linewidth=2)
plot(Txy.T[1],Txy.T[2],'ro',markersize=10)
plot([0,1],[0,1],'k--')
axis('equal')
ylim([0,1])
xlim([0,1])
xlabel('x: ' + A)
ylabel('y: ' + A)
title('xy Diagram: ' + A + '/' + B)
grid()
def P(T,x):
z = 0
for k in range(len(x)):
z += x[k]*Psat[species[k]](T)
return z
Tbub(760,1)
80.0999933615606
P(85,.1)
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-22-c974998316dd> in <module>() ----> 1 P(85,.1) <ipython-input-20-892885dfefc2> in P(T, x) 1 def P(T,x): 2 z = 0 ----> 3 for k in range(len(x)): 4 z += x[k]*Psat[species[k]](T) 5 return z TypeError: object of type 'float' has no len()
P(84
Mixtures of Ethylene glycol and water are widely used for engine cooling in automobiles. The following chart [Source: Ethylene Glycol Product Guide, MEGlobal] shows the boiling point of ethylene glycol/water mixtures as a function of solution composition and pressure. Construct your own chart based on Raoult's law and Antoine's equations, and compare the results.
E = 'ethylene-glycol'
W = 'water'
MW = dict()
MW[E] = 62.07
MW[W] = 18.01528
Psat = dict()
Psat[E] = lambda T: 10**(8.0908 - 2088.9/(T + 203.5))
Psat[W] = lambda T: \
(T <= 60) and 10**(8.10765 - 1750.286/(T + 235.0)) or \
(T > 60) and 10**(7.96681 - 1668.21/(T + 228.0))
def Pbub(T,w):
x = (w/MW[E])/(w/MW[E] + (1-w)/MW[W])
return x*Psat[E](T) + (1-x)*Psat[W](T)
from scipy.optimize import brentq as fzero
def Tbub(P,w):
return fzero(lambda T: Pbub(T,w)-P, 0, 300)
w = linspace(0,1)
figure(figsize=(9,6))
plot(100*w,map(lambda w:Tbub(200,w),w))
plot(100*w,map(lambda w:Tbub(760,w),w))
plot(100*w,map(lambda w:Tbub(1520,w),w))
legend(['200 mmHg','760 mmHg','1520 mmHg'],'best')
tick_params(labelsize=14)
xlim(0,100)
ylim(50,300)
xlabel('Ethylene Glycol, % by Weight in Water',fontsize=14)
ylabel('Temperature, $^{\circ}C$',fontsize=14)
grid()