% PBR_DAE_sim.m % This program simulates the steady-state profile % in a Packed Bed Reactor (PBR) of the reaction % A <==> B + C, occuring on a solid catalyst in % contact with a gas stream of A, B, C, and a % non-reactive dilutent gas G. The reactor is assumed % to be isothermal and there are no mass transfer % limitations. Surface reaction is assumed to be % rate limiting with adsorption/desorption in % equilibrium. % Written by Kenneth J. Beers. % MIT Department of Chemical Engineering % April 13, 2005 function iflag_main = PBR_DAE_sim(); iflag_main = 0; % First, set the rate law parameter Rate = set_Rate(); % Next, set reactor parameters Reactor = set_Reactor(); % set initial state vector x_0 = set_initial_state(Rate,Reactor); % set mass matrix Mass = zeros(7,7); Mass(1:4,1:4) = eye(4); % set Options structure Options = odeset('Mass',Mass,'MassSingular','yes', ... 'MStateDependence','none'); % ask user to input mass of catalyst in reactor W_tot = input('Enter tot. cat. mass in PBR : '); % perform simulation [W_traj, x_traj] = ode15s(@PBR_calc_f, [0 W_tot], ... x_0, Options, Rate, Reactor); % plot results plot_results(W_traj,x_traj,Rate,Reactor); iflag_main = 1; return; % ------------------------------ % This routine sets the rate law parameters. function Rate = set_Rate(); % set reaction rate law parameters % moles of active sites per Kg of catalyst Rate.c_t = 1e-3; % adsorption equilibrium constant for A Rate.Ka_A = 4.2e-5; % in 1/Pa % adsorption equilibrium constant for B Rate.Ka_B = 2.5e-5; % in 1/Pa % forward surface reaction rate constant Rate.k_s = 30; % in 1/s % equilibrium constant for surface reaction Rate.Keq_s = 9.12e5; % in Pa return; % ------------------------------ % This routine sets the reactor parameters. function Reactor = set_Reactor(); % diameter of catalyst particles Reactor.D_p = 0.005; % in m % void fraction of bed Reactor.phi = 0.64; % cross sectional area of bed Reactor.A_c = 0.0079; % in m^2 % density of solid catalyst phase Reactor.rho_s = 900; % in Kg/m^3 % set inlet gas properties % total pressure of inlet stream Reactor.P_0 = 101325; % in Pa % partial pressure of A in inlet stream Reactor.p_A0 = 0.1*101325; % in Pa % inlet volumetric flow rate Reactor.vflow_0 = 0.001; % in m^3/s % inlet temperature Reactor.T_0 = 373; % in K % molar flow rate of A in feed stream Reactor.F_A0 = Reactor.p_A0*Reactor.vflow_0 ... / 8.314 / Reactor.T_0; % in mol/s % molar flow rate of dilutent gas in feed stream Reactor.F_G0 = (Reactor.P_0 - Reactor.p_A0) ... * Reactor.vflow_0/8.314/Reactor.T_0; % in mol/s % total molar flow rate of feed stream in mol/s Reactor.F_tot0 = Reactor.F_A0 + Reactor.F_G0; % density of gas phase at inlet conditions Reactor.rho_0 = 2.9; % in Kg/m^3 % viscosity of gas pahse Reactor.mu = 2e-5; % in Pa*s % superficial mass velocity Reactor.gamma = Reactor.rho_0 ... *Reactor.vflow_0/Reactor.A_c; % Ergun constant beta_0 for model of pressure % drop across packed bed, assumed constant viscosity var1 = 150*(1-Reactor.phi)*Reactor.mu/Reactor.D_p; var2 = Reactor.gamma*(1-Reactor.phi) ... /Reactor.rho_0/Reactor.D_p/(Reactor.phi^3); Reactor.beta_0 = var2*(var1 + 1.75*Reactor.gamma); return; % ------------------------------ % This routine initializes the state of % the system to the inlet conditions. function x_0 = set_initial_state(Rate,Reactor); x_0 = zeros(7,1); % allocate memory R = 8.314; % ideal gas constant in SI units x_0(1) = Reactor.F_A0; % molar flow rate of A x_0(2) = 0; % molar flow rate of B x_0(3) = 0; % molar flow rate of C x_0(4) = Reactor.P_0; % pressure % following values from isotherm of A c_v = Rate.c_t/(1+Rate.Ka_A*Reactor.p_A0); c_AS = Rate.Ka_A*Reactor.p_A0*c_v; x_0(5) = c_AS; % conc. of absorbed A x_0(6) = 0; % conc. of absorbed B x_0(7) = c_v; % conc. of vacant sites return; % ------------------------------ % This routine returns the function vector for % the PBR model function f = PBR_calc_f(W, x, Rate, Reactor); f = zeros(7,1); % extract state variables F_A = x(1); % molar flow rate of A F_B = x(2); % molar flow rate of B F_C = x(3); % molar flow rate of C P = x(4); % total pressure c_AS = x(5); % conc. of absorbed A c_BS = x(6); % conc. of adsorbed B c_v = x(7); % conc. of vacant sites % compute total molar flow rate F_tot = F_A + F_B + F_C + Reactor.F_G0; % compute partial pressures in gas phase p_A = P*F_A/F_tot; p_B = P*F_B/F_tot; p_C = P*F_C/F_tot; % compute volumetric flow rate in m^3/s R = 8.314; % ideal gas constant in SI units T = Reactor.T_0; % isothermal operation vflow = F_tot*R*T/P; % volumetric flow rate % compute surface reaction rate r_R = Rate.k_s*(c_AS - c_BS*p_C/Rate.Keq_s); % Next, evaluate derivative functions. % mole balance on A f(1) = -r_R; % mole balance on B f(2) = r_R; % mole balance on C f(3) = r_R; % pressure drop across packed bed var1 = Reactor.beta_0/Reactor.A_c ... /(1-Reactor.phi)/Reactor.rho_s; f(4) = -var1*(Reactor.P_0/P)... *(F_tot/Reactor.F_tot0); % adsorption equilibrium of A f(5) = Rate.Ka_A*p_A*c_v - c_AS; % adsorption equilibrium of B f(6) = Rate.Ka_B*p_B*c_v - c_BS; % site balance f(7) = Rate.c_t - c_v - c_AS - c_BS; return; % ------------------------------ % This routine plots the results function iflag = plot_results(... W_traj,x_traj,Rate,Reactor); iflag = 0; figure; % first plot is of molar flow rates subplot(2,1,1); plot(W_traj,x_traj(:,1)); % F_A hold on; plot(W_traj,x_traj(:,2),'--'); % F_B plot(W_traj,x_traj(:,3),'-.'); % F_C xlabel('W (Kg)'); ylabel('F_j (mol/s)'); title('Molar flow rates'); legend('A','B','C','Location','Best'); % second plot is of catalyst concentrations subplot(2,1,2); plot(W_traj,x_traj(:,5)); % c_AS hold on; plot(W_traj,x_traj(:,6),'--'); % c_BS plot(W_traj,x_traj(:,7),'-.'); % c_v xlabel('W (Kg)'); ylabel('c_j (mol/Kg-cat)'); title('catalyst concentrations'); legend('AS','BS','v','Location','Best'); iflag = 1; return;