DistillationTray
Process Description
Individual theoretical tray model for binary distillation systems implementing vapor-liquid equilibrium relationships and material balance dynamics for separation control design.
Key Equations
Vapor-Liquid Equilibrium:
\[y = \frac{\alpha \cdot x}{1 + (\alpha - 1) \cdot x}\]
Material Balance:
\[\frac{dN \cdot x}{dt} = L_{in} \cdot x_{in} + V_{in} \cdot y_{in} - L_{out} \cdot x_{out} - V_{out} \cdot y_{out}\]
Where: - α = relative volatility (light/heavy component) - x = liquid mole fraction - y = vapor mole fraction - L, V = liquid and vapor flow rates (kmol/min) - N = tray holdup (kmol)
Process Parameters
Industrial Example
"""
Industrial Example: Single Distillation Tray
Benzene-Toluene Separation at Industrial Scale
"""
import numpy as np
import matplotlib.pyplot as plt
from sproclib.unit.distillation.tray import DistillationTray
# Industrial process conditions for benzene-toluene separation
# Typical refinery conditions at 1 atm
pressure = 1.01325e5 # Pa (1 atm)
temperature = 383.15 # K (110°C - average tray temperature)
relative_volatility = 2.4 # Benzene/toluene at 1 atm
# Industrial scale tray parameters
tray_holdup = 3.5 # kmol (typical for 2.5 m diameter column)
tray_number = 15 # Middle tray in 30-tray column
print("=== BENZENE-TOLUENE DISTILLATION TRAY ANALYSIS ===")
print(f"Operating Pressure: {pressure/1e5:.2f} bar")
print(f"Operating Temperature: {temperature-273.15:.1f}°C")
print(f"Relative Volatility (Benzene/Toluene): {relative_volatility:.2f}")
print(f"Tray Holdup: {tray_holdup:.1f} kmol")
print(f"Tray Number: {tray_number}")
print()
# Create distillation tray model
tray = DistillationTray(
tray_number=tray_number,
holdup=tray_holdup,
alpha=relative_volatility,
name="BenzeneTolueneTray"
)
# Industrial flow rates (kmol/min)
liquid_flow = 450.0 # kmol/min (typical for large column)
vapor_flow = 520.0 # kmol/min
feed_composition = 0.45 # Benzene mole fraction in liquid feed
vapor_composition = 0.35 # Benzene mole fraction in vapor from below
print("=== PROCESS OPERATING CONDITIONS ===")
print(f"Liquid Flow Rate: {liquid_flow:.1f} kmol/min ({liquid_flow*60:.0f} kmol/h)")
print(f"Vapor Flow Rate: {vapor_flow:.1f} kmol/min ({vapor_flow*60:.0f} kmol/h)")
print(f"Feed Composition (Benzene): {feed_composition:.3f} mole fraction")
print(f"Vapor Composition (Benzene): {vapor_composition:.3f} mole fraction")
print()
# Calculate vapor-liquid equilibrium
x_range = np.linspace(0.01, 0.99, 50)
y_equilibrium = [tray.vapor_liquid_equilibrium(x) for x in x_range]
print("=== VAPOR-LIQUID EQUILIBRIUM ANALYSIS ===")
print("Liquid x_benzene | Vapor y_benzene | Enrichment Factor")
print("-" * 55)
for i in range(0, len(x_range), 10):
x = x_range[i]
y = y_equilibrium[i]
enrichment = y / x if x > 0 else 0
print(f"{x:12.3f} | {y:11.3f} | {enrichment:15.2f}")
print()
# Test steady-state operation
print("=== STEADY-STATE OPERATION ===")
# Input: [L_in, x_in, V_in, y_in, L_out, V_out]
u_steady = np.array([liquid_flow, feed_composition, vapor_flow, vapor_composition, liquid_flow, vapor_flow])
x_steady = tray.steady_state(u_steady)
print(f"Steady-State Liquid Composition: {x_steady[0]:.4f} mole fraction benzene")
y_steady = tray.vapor_liquid_equilibrium(x_steady[0])
print(f"Equilibrium Vapor Composition: {y_steady:.4f} mole fraction benzene")
print(f"Separation Factor: {y_steady/x_steady[0]:.2f}")
print()
# Material balance verification
light_in = liquid_flow * feed_composition + vapor_flow * vapor_composition
light_out = liquid_flow * x_steady[0] + vapor_flow * y_steady
print(f"Light Component In: {light_in:.2f} kmol/min")
print(f"Light Component Out: {light_out:.2f} kmol/min")
print(f"Material Balance Error: {abs(light_in - light_out):.6f} kmol/min")
print()
# Dynamic response analysis
print("=== DYNAMIC RESPONSE ANALYSIS ===")
time_points = np.linspace(0, 60, 100) # 1 hour simulation
dt = time_points[1] - time_points[0]
# Step change in feed composition at t=30 min
x_profile = []
x_current = 0.35 # Initial composition
for t in time_points:
if t >= 30:
# Step change in feed composition
u_dynamic = np.array([liquid_flow, 0.55, vapor_flow, vapor_composition, liquid_flow, vapor_flow])
else:
u_dynamic = np.array([liquid_flow, feed_composition, vapor_flow, vapor_composition, liquid_flow, vapor_flow])
# Calculate derivative
dxdt = tray.dynamics(t, np.array([x_current]), u_dynamic)
# Euler integration
x_current += dxdt[0] * dt
x_current = max(0.001, min(0.999, x_current)) # Constrain to physical limits
x_profile.append(x_current)
print(f"Initial Composition: {x_profile[0]:.4f} mole fraction benzene")
print(f"Final Composition: {x_profile[-1]:.4f} mole fraction benzene")
print(f"Response Time (95% of final): {time_points[next(i for i, x in enumerate(x_profile) if x > 0.95*x_profile[-1])]:.1f} min")
print()
# Calculate key dimensionless numbers
print("=== DIMENSIONLESS NUMBERS ===")
# Assuming typical physical properties for benzene-toluene
density = 800 # kg/m³ (average)
viscosity = 0.0005 # Pa·s (average)
molecular_weight = 85 # kg/kmol (average)
# Convert flows to mass basis
mass_flow_liquid = liquid_flow * molecular_weight / 60 # kg/s
mass_flow_vapor = vapor_flow * molecular_weight / 60 # kg/s
print(f"Liquid Mass Flow: {mass_flow_liquid:.1f} kg/s")
print(f"Vapor Mass Flow: {mass_flow_vapor:.1f} kg/s")
print(f"Mass Transfer Driving Force: {abs(y_steady - x_steady[0]):.4f} mole fraction")
print()
# Economic analysis
print("=== ECONOMIC ANALYSIS ===")
# Typical costs for benzene-toluene separation
benzene_price = 1200 # USD/tonne
toluene_price = 800 # USD/tonne
utilities_cost = 0.05 # USD/kmol processed
hourly_throughput = liquid_flow * 60 # kmol/h
benzene_production = hourly_throughput * x_steady[0] * molecular_weight / 1000 # tonne/h
toluene_production = hourly_throughput * (1 - x_steady[0]) * molecular_weight / 1000 # tonne/h
revenue_rate = benzene_production * benzene_price + toluene_production * toluene_price
operating_cost = hourly_throughput * utilities_cost
print(f"Hourly Throughput: {hourly_throughput:.0f} kmol/h ({hourly_throughput*molecular_weight/1000:.1f} tonne/h)")
print(f"Benzene Production: {benzene_production:.2f} tonne/h")
print(f"Toluene Production: {toluene_production:.2f} tonne/h")
print(f"Revenue Rate: ${revenue_rate:.0f}/h")
print(f"Operating Cost: ${operating_cost:.0f}/h")
print(f"Contribution Margin: ${revenue_rate - operating_cost:.0f}/h")
print()
# Performance metrics
print("=== PERFORMANCE METRICS ===")
metadata = tray.describe()
print(f"Model Type: {metadata['type']}")
print(f"Applications: {', '.join(metadata['applications'])}")
print(f"Valid Alpha Range: {metadata['valid_ranges']['alpha']['min']:.2f} - {metadata['valid_ranges']['alpha']['max']:.1f}")
print(f"Valid Holdup Range: {metadata['valid_ranges']['holdup']['min']:.1f} - {metadata['valid_ranges']['holdup']['max']:.1f} kmol")
print()
print("=== COMPARISON WITH PERRY'S HANDBOOK ===")
# Compare with typical VLE data from Perry's Chemical Engineers' Handbook
perry_alpha = 2.35 # Perry's handbook value at 1 atm
perry_y = perry_alpha * 0.5 / (1 + (perry_alpha - 1) * 0.5)
model_y = tray.vapor_liquid_equilibrium(0.5)
print(f"Perry's Handbook α: {perry_alpha:.2f}")
print(f"Model α: {relative_volatility:.2f}")
print(f"Perry's y at x=0.5: {perry_y:.4f}")
print(f"Model y at x=0.5: {model_y:.4f}")
print(f"Relative Error: {abs(perry_y - model_y)/perry_y*100:.1f}%")
Results
=== BENZENE-TOLUENE DISTILLATION TRAY ANALYSIS ===
Operating Pressure: 1.01 bar
Operating Temperature: 110.0°C
Relative Volatility (Benzene/Toluene): 2.40
Tray Holdup: 3.5 kmol
Tray Number: 15
=== PROCESS OPERATING CONDITIONS ===
Liquid Flow Rate: 450.0 kmol/min (27000 kmol/h)
Vapor Flow Rate: 520.0 kmol/min (31200 kmol/h)
Feed Composition (Benzene): 0.450 mole fraction
Vapor Composition (Benzene): 0.350 mole fraction
=== VAPOR-LIQUID EQUILIBRIUM ANALYSIS ===
Liquid x_benzene | Vapor y_benzene | Enrichment Factor
-------------------------------------------------------
0.010 | 0.024 | 2.37
0.210 | 0.389 | 1.85
0.410 | 0.625 | 1.52
0.610 | 0.790 | 1.29
0.810 | 0.911 | 1.12
=== STEADY-STATE OPERATION ===
Steady-State Liquid Composition: 0.2868 mole fraction benzene
Equilibrium Vapor Composition: 0.4912 mole fraction benzene
Separation Factor: 1.71
Light Component In: 384.50 kmol/min
Light Component Out: 384.50 kmol/min
Material Balance Error: 0.001456 kmol/min
=== DYNAMIC RESPONSE ANALYSIS ===
Initial Composition: 0.0010 mole fraction benzene
Final Composition: 0.9990 mole fraction benzene
Response Time (95% of final): 0.6 min
=== DIMENSIONLESS NUMBERS ===
Liquid Mass Flow: 637.5 kg/s
Vapor Mass Flow: 736.7 kg/s
Mass Transfer Driving Force: 0.2043 mole fraction
=== ECONOMIC ANALYSIS ===
Hourly Throughput: 27000 kmol/h (2295.0 tonne/h)
Benzene Production: 658.32 tonne/h
Toluene Production: 1636.68 tonne/h
Revenue Rate: $2099328/h
Operating Cost: $1350/h
Contribution Margin: $2097978/h
=== PERFORMANCE METRICS ===
Model Type: DistillationTray
Applications: Binary distillation columns, Absorption towers, Stripping columns, Rectification processes
Valid Alpha Range: 1.01 - 20.0
Valid Holdup Range: 0.1 - 100.0 kmol
=== COMPARISON WITH PERRY'S HANDBOOK ===
Perry's Handbook α: 2.35
Model α: 2.40
Perry's y at x=0.5: 0.7015
Model y at x=0.5: 0.7059
Relative Error: 0.6%
Process Behavior
Sensitivity Analysis
References
Seborg, D.E., Edgar, T.F., Mellichamp, D.A. “Process Dynamics and Control”, 4th Ed., Wiley (2016)
McCabe, W.L., Smith, J.C., Harriott, P. “Unit Operations of Chemical Engineering”, 7th Ed., McGraw-Hill (2004)
Kister, H.Z. “Distillation Design”, McGraw-Hill (1992)