% 10.34 - Fall 2006 % Hw Set #7 - Problem #2 % Rob Ashcraft - Oct. 20, 2006 %This function solve the reactor optimization problem in Beers' text 5.B.4. % This implementation uses a scaled variable LN(V_rxtr) as well as the % other normal variables. function p2_main_logV clear; clc; % rate constant data at 298K and 310K for k1 --> k5 T_data = [298, 310]; % kelvin k_T = [0.01, 0.02; 0.01, 0.02; 0.001, 0.005; 0.001, 0.005; 0.001, 0.005]; % L/mol-s T_plot = linspace(273,335,20); for i=1:length(k_T) EaR(i,1) = -log(k_T(i,1)/k_T(i,2)) / (1/T_data(1) - 1/T_data(2)); % solve for Ea/R for each reaction Af(i,1) = k_T(i,1)*exp(EaR(i)/T_data(1)); % solve for the A-factor using k(298K) k_plot(:,i) = Af(i).*exp(-EaR(i)./T_plot); % make a vector k(T) to plot end % plot the rate constants to make sure they fit the data figure; semilogy(T_data,k_T(1,:),'ok',T_plot,k_plot(:,1),'-',T_data,k_T(3,:),'*k',T_plot,k_plot(:,3),'--'); xlabel('Temperature (K)'); ylabel('Rate Constant (L/mole-s)'); legend('k_1 and k_2 data','k_1 and k_2 fit','k_3, k_4, k_5 data','k_3, k_4, k_5 fit','location','SouthEast'); % now deal with the reactor problem V_flow = 1; % L/s % initial guesses for the optimization: C_Ao_guess = 1; % molar C_Bo_guess = 1; % molar T_guess = 315; % Kelvin V_rxtr_guess = 5000; % liters % Choose the Volume variable to be LN(V) var0 = [C_Ao_guess; C_Bo_guess; T_guess; log(V_rxtr_guess)]; % note that in the scaled case, you do not very high tolerances. The % tolerance in this case only serves to increase the precision of the % solution (even default tolerance will get you very close) options = optimset('Display','iter','TolFun',1e-10,'TolX',1e-10); % Define the constraint that Ca + Cb < 2 M A = [1, 1, 0, 0]; b = 2; % Include the given upper and lower bounds on the system varaible lb = [0; 0; 298; log(10)]; ub = [2; 2; 335; log(10000)]; % call fmincon to solve the problem [var, fval] = fmincon(@obj_fun,var0,A,b,[],[],lb,ub,[],options,V_flow,Af,EaR); disp(['Inlet [A] = ',num2str(var(1)),' M']); disp(['Inlet [B] = ',num2str(var(2)),' M']); disp(['Reactor Temperature = ',num2str(var(3)),' K']); disp(['Reactor Volume = ',num2str(exp(var(4))),' L']); disp(['Outlet [C] = ',num2str(-fval),' M']); C_Ao = var(1); C_Bo = var(2); T = var(3); V_rxtr = exp(var(4)); % Since we solved for [C]final by integrating to the SS condition, it is % useful to make sure that the reactor actually reach steady-state. We can % perform a non-rigorous check by integrating based on the optimal % conditions, and then visually inspect the plot. This does not mean that % all other parameters sets encountered during the optimization also % reached SS, but it is a useful check none-the-less t_span = [0, 1e5]; [time, C_all] = ode45(@rxtr_dCdt_ode,t_span,zeros(8,1),[],C_Ao,C_Bo,T,V_rxtr,V_flow,Af,EaR); figure; plot(time,C_all(:,1),'--',time,C_all(:,2),':',time,C_all(:,3),'-',time,C_all(:,4),'-.'); xlabel('Time (s)'); ylabel('Concentration (M)'); title('Did Reactor Reach Steady-State?'); legend('[A]','[B]','[C]','[D]'); % Since we found out early that the V_rxtr term was causing problems, it is % also useful to look at the cost function as a function of V_rxtr, and % make sure our fmincon solution appears to be at the minimum. test = logspace(1,4,50); for i=1:length(test) cost_i(i) = obj_fun([var(1:3);log(test(i))],V_flow,Af,EaR); end figure; semilogx(test,cost_i,'-',V_rxtr,fval,'o') xlabel('Reactor Volume (L)'); ylabel('Cost Function (-[C]_o_u_t M)'); legend('Cost Function','fmincon Solution'); return; % Other functions used in the program %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Define the function called by fmincon with the cost function function cost = obj_fun(var,V_flow,Af,EaR) C_Ao = var(1); C_Bo = var(2); T = var(3); LN_V_rxtr = var(4); V_rxtr = exp(var(4)); % since we are using LN(V) as the variable C_guess = [1; 1; 0; 0; 0; 0; 0; 0]; % we solve for [C]final by integrating to a SS condition. You must % make sure you integrate for a long enough time to achieve SS t_span = [0, 1e5]; [time, C_all] = ode15s(@rxtr_dCdt_ode,t_span,C_guess,odeset('RelTol',1e-8),C_Ao,C_Bo,T,V_rxtr,V_flow,Af,EaR); % the cost function in the negative of [C]final cost = -(C_all(end,3)); return; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Define the reactor governing equations as a function. It will return % dC/dt for each of the species in the reactor function dAlldt = rxtr_dCdt_ode(t,C_all,C_Ao,C_Bo,T,V_rxtr,V_flow,Af,EaR) % all of the C variable are concentrations in moles/L A = C_all(1); B = C_all(2); C = C_all(3); D = C_all(4); S1 = C_all(5); S2 = C_all(6); S3 = C_all(7); S4 = C_all(8); k = Af.*exp(-EaR./T); % calculates the rate constants dAdt = -k(1)*A*B - k(3)*A*D - k(4)*A*B + V_flow/V_rxtr*(C_Ao - A); dBdt = -k(1)*A*B - k(2)*B*C - k(4)*A*B - k(5)*B*C + V_flow/V_rxtr*(C_Bo - B); dCdt = k(1)*A*B - k(2)*B*C - k(5)*B*C - V_flow/V_rxtr*C; dDdt = k(1)*A*B + k(2)*B*C - k(3)*A*D - V_flow/V_rxtr*D; dS1dt = k(2)*B*C - V_flow/V_rxtr*S1; dS2dt = k(3)*A*D - V_flow/V_rxtr*S2; dS3dt = k(4)*A*B - V_flow/V_rxtr*S3; dS4dt = k(5)*B*C - V_flow/V_rxtr*S4; dAlldt = [dAdt; dBdt; dCdt; dDdt; dS1dt; dS2dt; dS3dt; dS4dt]; return;