Author | Esteban Richmond-Salazar |
Date | 2020-06-09T22:29:48 |
Project | c8d6174e-82a9-4a2a-ba1f-b0b5a9e871b3 |
Location | Tareas/Tarea 5 (2020) Adsorción y teoría de movimiento del soluto.sagews |
Original file | Tarea 5 (2020) Adsorción y teoría de movimiento del soluto.sagews |
Valor: 22 puntos
Referencia: Datos del problema 12.1-1 de Geankoplis (1998)
A continuación se muestran los datos de la isoterma de adsorción de glucosa (en agua) utilizando alúmina.
c / (g/cm3) |
0,0040 |
0,0087 |
0,019 |
0,024 |
0,094 |
0,195 |
q / (g/g) |
0,026 |
0,053 |
0,075 |
0,082 |
0,123 |
0,129 |
# ==================== Problema 1 ====================
c = [0.004, 0.0087, 0.019, 0.024, 0.094, 0.195] # g/cm³, kg/L
q = [0.026, 0.053 , 0.075, 0.082, 0.123, 0.129] # g/g, kg/kg
html('<h2>Solución</h2>')
datos_eq = zip(c,q) # Combina los datos de equilibrio
%var c_A, q_A_max, K_Ac, n
L = 15 # [L]
c0 = 1.30 # [mol/L] antes 1.39
M = 180.156 # [kg/kmol]
S1 = 20 # [kg]
q0 = 0 # [kg/kg]
S2 = 20 # [kg]
c0 = c0*M/1000 # [kg/L]
html('<h3>Parte a) Ajustar a el modelo de Langmuir y Freundlich</h3>')
show("===== Isoterma de Langmuir =====")
qA_L(c_A) = q_A_max*K_Ac*c_A / (1+K_Ac*c_A)
ajuste = find_fit(datos_eq, qA_L, solution_dict = True)
qA_L = qA_L(q_A_max= numerical_approx(ajuste[q_A_max], digits = 4), K_Ac= numerical_approx(ajuste[K_Ac], digits=4))
show(r"$K_{A,c} = $ ", numerical_approx(ajuste[K_Ac], digits=4), r" L/kg; $q_{A,máx} = $", numerical_approx(ajuste[q_A_max], digits=4), " kg/kg")
show("$q_{A_L} = $", qA_L)
show("===== Isoterma de Freundlich =====")
qA_F(c_A) = K_Ac*c_A^(1/n)
ajuste = find_fit(datos_eq, qA_F, solution_dict = True)
qA_F = qA_F(n= numerical_approx(ajuste[n], digits=4), K_Ac=numerical_approx(ajuste[K_Ac], digits=4))
show(r"$K_{A,c} = $ ", numerical_approx(ajuste[K_Ac], digits=4), r" L/kg; $n = $", numerical_approx(ajuste[n], digits=4))
show("$q_{A_F} = $", qA_F)
# Gráfica
gr_datos = scatter_plot(datos_eq, axes_labels = ['$c_A/(\\mathrm{kg/L})$', '$q_A/(\\mathrm{kg/kg})$'])
gr_Langm = plot(qA_L, xmin = 0, xmax = max(max(c),c0), legend_label = 'Langmuir', color = 'blue')
gr_Frlch = plot(qA_F, xmin = 0, xmax = max(c), legend_label = 'Freundlich', color = 'green')
show(gr_datos+gr_Langm+gr_Frlch)
html('<h3>Parte b) Una etapa</h3>')
def Calcula_etapa(W_L, W_S, c_entra, q_entra, q_isot):
R.<c_sale> = QQ[]
q_sale = q_isot(c_sale)
f = c_sale - (W_S/W_L * (q_entra - q_sale) + c_entra)
csale = find_root(f, 0, c_entra)
return [csale, q_sale(c_sale=csale)]
c1, q1 = Calcula_etapa(L, S1, c0, q0, qA_L)
show (r'$c_1 = %s$ kg/L; $q_1 = %s$ kg/kg' %(numerical_approx(c1, digits = 3), numerical_approx(q1, digits=3)))
html('<h3>Parte c) Dos etapas a flujo cruzado, idénticas cantidades de sólido</h3>')
c2, q2 = Calcula_etapa(L, S2, c1, q0, qA_L)
show (r'$c_2 = %s$ kg/L; $q_2 = %s$ kg/kg' %(numerical_approx(c2, digits = 3), numerical_approx(q2, digits=3)))
gr_etapa1 = line([(c0,q0),(c1,q1),(c1,0)], color = 'purple', legend_label = 'Etapa 1')
gr_etapa2 = line([(c1,q0),(c2,q2),(c2,0)], color = 'magenta', legend_label = 'Etapa 2')
show(gr_datos+gr_Langm+gr_etapa1+gr_etapa2)
html('<h3>Parte d) Dos etapas a flujo cruzado, calcular sólido mínimo</h3>')
S1m = L*(c0-c_A)/(qA_L(c_A) + q0) # Alúmina requerida en la etapa 1 para obtnener una concentración c_A
S2m = L*(c_A-c2)/(qA_L(c_A=c2) + q0) # Alúmina requerida en la etapa 2 con una concentración de entrada c_A
STm = S1m+S2m # Alúmina total
S_Tm, c1 = find_local_minimum(STm, c2, c0)
show (r"$S_{T}$ /kg $=$", STm)
show (r"$S_{T, mín}= %s$ kg; $c_{1}= %s$ kg/L" %(numerical_approx(S_Tm, digits=3), numerical_approx(c1, digits=3)))
show (r"$Ahorro = %s $ kg" %(numerical_approx(((S1+S2)-S_Tm), digits=3)))
show (r"$S_{1}= %s$ kg; $S_{2}= %s$ kg" %(numerical_approx(S1m(c1), digits=3), numerical_approx(S2m(c1), digits=3)))
html('<h3>Parte e) Una etapa con total obtenido en d)</h3>')
c1, q1 = Calcula_etapa(W_L=L, W_S=S_Tm, c_entra=c0, q_entra=q0, q_isot=qA_L)
show (r'$c_1 = %s$ kg/L; $q_1 = %s$ kg/kg' %(numerical_approx(c1, digits = 3), numerical_approx(q1, digits=3)))
# *** Final del código ***
Valor: 15 puntos
Referencia: Adaptado de Problema 12.3-2 Geankoplis (1998)
Mediante cribas moleculares se elimina vapor de agua del nitrógeno gaseoso en un lecho relleno a 28.3 °C. La altura de la columna es de 0.268 m y la densidad del lecho es 712.8 kg/m³. La concentración inicial del agua en el sólido es y la velocidad de masa del nitrógeno gaseoso es de 4052 kg/(m² h).
La concentración inicial de agua en el gas es .
A continuación se muestran los datos experimentales
t / ( h ) |
0 |
9 |
9.2 |
9.6 |
10 |
10.4 |
10.8 |
11.25 |
11.5 |
12 |
12.5 |
12.8 |
Y*106 /(kg/kg) |
0.6 |
0.6 |
2.6 |
21 |
91 |
235 |
418 |
630 |
717 |
855 |
906 |
926 |
# ==================== Problema 2 ====================
html('<h2>Solución</h2>')
# Datos experimentales
lista_t = [0 , 9 , 9.2, 9.6, 10, 10.4, 10.8, 11.25, 11.5, 12, 12.5, 12.8] # [h]
#lista_t = [0 , 4 , 4.2, 4.6, 5, 5.4, 5.8, 6.25, 6.5, 7, 7.5, 7.8] # [h]
lista_Y = [0.6, 0.6, 2.6, 21 , 91, 235 , 418 , 630 , 717 , 855, 906 , 926 ] # [*10^-6 kg/kg]
datos_t_Y = zip(lista_t, lista_Y)
# Datos adicionales
t = 28.3 # [°C]g/kg
P = 1 # [atm]
L = 0.268 # [m]
rho_b = 712.8 # [kg/m^3]
q_0 = 0.01 # [kg/kg]
G_s = 4052 # [kg/(m^2 h)]
Y_0 = 926 # [*10^-6 kg/kg]
Y_rup = 0.02*Y_0 # [*10^-6 kg/kg]
L_parte_b = 0.4 # [m]
t_rupt_c = 24 # [h]
G_s_c = 6000 # [kg/(m^2 h)]
# Ajuste de datos
lista_Yn = [Y/Y_0 for Y in lista_Y]
datos_t_Yn = zip(lista_t, lista_Yn)
a, b, t = var('a, b, t')
modelo(t) = Y_0/2 * (1 + erf(a*t-b))
ajuste = find_fit(datos_t_Y, modelo, initial_guess=[1, max(lista_t)], solution_dict = True)
Y(t) = modelo(a=ajuste[a], b=ajuste[b])
Y(t)
# Cálculo de tiempos
t_sat = max(lista_t)
t_ideal = numerical_approx(numerical_integral(1-Y/Y_0, 0, max(lista_t))[0], digits = 4)
t_rupt = find_root(Y(t) == Y_rup, 0, t_sat)
print "t_rupt =", numerical_approx(t_rupt, digits = 3), "h"
print "t_ideal =", t_ideal.numerical_approx(digits = 3), "h"
print "t_agot =", t_sat.numerical_approx(digits = 3), "h"
# Cálculo de fracción sin utilizar
qA_rup = G_s*Y_0*10^-6/(L*rho_b) * numerical_integral(1-Y/Y_0, 0, t_rupt)[0] #+ q_0
print "qA_rupt =", qA_rup.numerical_approx(digits = 3), "kg/kg"
qA_max = G_s*Y_0*10^-6/(L*rho_b) * t_ideal + q_0
print "qA_max =", qA_max.numerical_approx(digits = 3), "kg/kg"
f_util = qA_rup/qA_max
f_nout = 1-f_util
print "Fracción utilizada =", f_util.numerical_approx(digits = 3)
print "Fracción no utilizada =", f_nout.numerical_approx(digits = 3)
LES = L*f_util
LUB = L*f_nout
print "LUB =", LUB.numerical_approx(digits = 3), "m"
scatter_plot(datos_t_Yn, axes_labels = ["$t/(\mathrm{h})$", ""]) \
+ plot(Y/Y_0, xmin = 0, xmax=15, legend_label = "$Y/Y_0$", color = 'orange') \
+ plot(1-Y/Y_0, xmin = 0, xmax=15, legend_label = "$1-Y/Y_0$", color = 'purple') \
+ plot(unit_step(t-t_ideal), xmax = 15, legend_label = "$1-Y_{ideal}/Y_0$")
print "=== Parte b ==="
LES_b = L_parte_b - LUB
# LES_2/t_rup2 = LES/t_rup
t_rupt_b = LES_b/LES*t_rupt
print "LES =", LES_b.numerical_approx(digits = 3), "m"
print "t_rupt =", t_rupt_b.numerical_approx(digits = 3), "h"
print "=== Parte c ==="
LUB_c = LUB * G_s_c/G_s
# Despejando LES de q_max = m_sat/m_S = (G_s * Y0 * t_ideal)/(A_c * LES * rho_b)
LES_c = G_s*Y_0*10^-6*t_rupt_c/(rho_b*qA_max)
L_c = LES_c + LUB_c
print "Nuevo LUB =", LUB_c.numerical_approx(digits = 3), "m"
print "Nuevo LES =", LES_c.numerical_approx(digits = 3), "m"
print "Nueva L =", L_c.numerical_approx(digits = 3), "m"
# *** Final del código ***
Valor: 24 puntos
Referencia: Esteban Richmond (2019)
Una columna de 6 cm de diámetro interno se rellena con 80 cm de alúmina activada. Al inicio se hace pasar ciclohexano puro a través de la columna por unos 5 min, luego de esto se introduce una alimentación de antraceno disuelto en ciclohexano a una concentración de 0.010 mol/L y se mantiene constante durante 10 min, luego se aumenta la concentración de la alimentación a 0.015 mol/L y se mantiene así por 15 min, finalmente se introduce ciclohexano puro por 60 min.
En todo momento el flujo alimentado se mantiene estable en 0,30 L/min.
Aplique la teoría del movimiento del soluto y elabore una gráfica con el perfil de concentración a la salida durante el tiempo de la corrida (90 min de duración).
Datos:
Isoterma de Langmuir:
,
kg/m³ (densidad aparente del lecho en ciclohexano)
kg/m³,
# ==================== Problema 3 ====================
html('<h2>Solución</h2>')
cA = var('cA')
# F = Dar flujo y área transversal, con ello calcular u_S
F = 0.30/1000 # m³/min
Dc = 6/100 # m
Ac = pi/4*Dc^2
Hc = 80 # cm
t0 = 0 # min
c0 = 0 # mol/L
t1 = 5 # min inicio alimentación c1
c1 = 0.01 # mol/L
t2 = t1+10 # min inicio alimentación c2
c2 = 0.015 # mol/L
t3 = t2+15 # min inicio alimentación c3
c3 = 0 # mol/L
t4 = t3+60 # min final operación
u_s = F/Ac*100 # cm/min
print("u_s = %.3g cm/min"%u_s)
# Datos adicionales
eps_e = 0.4
eps_p = 0.1
Kd = 1.0
#rho_S = 1.465 # kg/L
qA(cA) = 20*cA/(1+350*cA)
rho_f = 0.78
rho_b = 1.2
rho_p = (rho_b - eps_e*rho_f)/(1-eps_e)
rho_S = (rho_p - eps_p*rho_f)/(1-eps_p)
print("Densidad de la partícula, rho_p = %.3g kg/L"%rho_p)
print("Densidad del sólido, rho_S = %.3g kg/L"%rho_S)
# Perfil alimentación
line([(t0, c0),(t1,c0),(t1,c1),(t2,c1),(t2,c2),(t3,c2),(t3,c3),(t4,c3)], xmin = t0, axes_labels=['$t$/min','$c_F$/(g/L)'])
print "Usando modelo para onda de choque"
DqDc (c_antes, c_desp) = (qA(cA = c_desp)-qA(cA = c_antes))/(c_desp-c_antes)
u_inter = u_s / eps_e
uA_sh(c_antes,c_desp) = u_inter/(1 + (1-eps_e)/eps_e * Kd + (1-eps_e)*(1-eps_p)/eps_e * rho_S * DqDc(c_antes,c_desp))
u_sh1 = uA_sh(c0, c1)
u_sh2 = uA_sh(c1, c2)
t_s1 = t1 + Hc/u_sh1
t_s2 = t2 + Hc/u_sh2
t_s3 = 0
print("Tiempo que tardaría en recorrer Hc onda de choque 1, Delta t_sh1 = %.3g min" %(Hc/u_sh1))
print("Tiempo que tardaría en recorrer Hc onda de choque 2, Delta t_sh2 = %.3g min" %(Hc/u_sh2))
print("Momento en que saldría onda de choque 1, t_sh1 = %.3g min" %(t_s1))
print("Momento en que saldría onda de choque 2, t_sh2 = %.3g min" %(t_s2))
#[t_s1, t_s2, t_s3]
show ("$u_{sh1} = $", numerical_approx(u_sh1, digits=4), " cm/min; $u_{sh2} = $", numerical_approx(u_sh2, digits=4), " cm/min")
if(t_s1 <= t_s2):
show("Las ondas de choque no coinciden")
gr_onda1 = line([(t0,0),(t1,0),(t_s1, Hc)], legend_label='Onda de choque 1')
gr_onda2 = line([(t0,0),(t2,0),(t_s2, Hc)], legend_label='Onda de choque 2', axes_labels=['$t$/min','$L$/cm'], color = 'green', xmax = t_s2+2,)
gr_perfil = line([(t0,c0),(t_s1,c0),(t_s1,c1)]) + line([(t_s1,c1),(t_s2,c1),(t_s2,c2),(t_s2+2,c2)], axes_labels=['$t$/min','$c_{sale}$/(g/L)'])
show(gr_onda1+gr_onda2)
show ("$t_{esc1} = $", numerical_approx(t_s1, digits=3), " min; $t_{esc2} = $", numerical_approx(t_s2, digits=3), " min")
else:
show("Las ondas de choque coinciden y se genera una tercera")
t_inter = t1+(t2-t1)*u_sh2/(u_sh2-u_sh1)
z_inter = u_sh1*(t_inter-t1)
u_sh3 = uA_sh(c0, c2)
show ("$u_{sh3} = $", numerical_approx(u_sh3, digits=4), " cm/min; $t_{inter} = $", numerical_approx(t_inter, digits=4), " min; $z_{inter} = $", numerical_approx(z_inter, digits=4), " cm")
t_s3 = t_inter+(Hc-z_inter)/u_sh3
gr_onda1 = line([(t0,0),(t1,0),(t_inter, z_inter)], legend_label='Onda de choque 1')
gr_onda2 = line([(t0,0),(t2,0),(t_inter, z_inter)], legend_label='Onda de choque 2', color = 'green')
gr_onda3 = line([(t_inter,z_inter),(t_s3, Hc)], legend_label='Onda de choque 3', color = 'red', axes_labels=['$t$/min','$L$/cm'], xmax = t_s3+2)
gr_perfil = line([(t0,c0),(t_s3,c0),(t_s3,c2)], axes_labels=['$t$/min','$c_{sale}$/(g/L)'])
show(gr_onda1+gr_onda2+gr_onda3)
print("Tiempo salida onda de choque 3 = %.3g min"%t_s3)
# Onda difusa
print "Onda difusa"
conc = [c2+i*(c3-c2)/9 for i in range(10)] # mol/m³.
u_A(cA) = u_inter/(1 + (1-eps_e)/eps_e * Kd + (1-eps_e)*(1-eps_p)/eps_e * rho_S * derivative(qA))
t_esc = [t3+numerical_approx(Hc/u_A(c), digits=4) for c in conc]
print "Tiempos de salida en minutos:", t_esc
t_max = t_esc[5]
lista_tc = zip(t_esc,conc)
lista_tc.insert(0,(max(t_s2,t_s3),c2))
#line([(t0, c0),(t1,c0),(t1,c1),(t_s1,c1),(t_max,c1)], xmax=t_max, axes_labels=['$t$/min','$c_F$/(mol/L)'])
gr_perfil + line(lista_tc, xmax = t4)
# ****** Fin solución problema 3 *****