% catalyst_nonisothermal_scan.m % % This MATLAB program plots the effectiveness factor vs. the % Thiele modulus for a catalyst pellet with first order reaction % at steady state in nonisothermal operation. No external mass or % heat transfer resistance is included, and Diriclet boundary % conditions are employed at the particle surface. To solve the % dimensionless PDE, finite differences are used with a non-uniform % grid. % % The dimensionless input parameters are : % Phi_TM = Thiele modulus % = product of particle radius and the square root of % the rate constant divided by the diffusivity % = measure of importance of diffusion % limitations % gamma = activation energy / (R*Ts), where % Ts is the known surface temperature % beta = Da*(-DH)*Cs/lambda/Ts, where Da is the diffusivity, % DH is the heat of reaction, Cs is the known surface % concentration, lambda is the thermal conductivity, % and Ts is the known surface temperature % = measure of importance of heat generation % by reaction vs. thermal conductivity % % Written K. Beers. MIT ChE. 9/21/2002 function iflag_main = catalyst_nonisothermal_scan(); cpu_start = cputime; iflag_main = 0; % First, have the user input the simulation parameters. disp('Enter simulation parameters, ...'); % problem parameters beta = input('Enter beta (row vector) : '); num_beta = length(beta); gamma = input('Enter gamma : '); % Thiele modulus bounds (log scale) Phi_TM_min = input('Enter min. Thiele modulus : '); Phi_TM_max = input('Enter max. Thiele modulus : '); num_TM = input('Enter number of Thiele modulus points : '); Phi_TM = logspace(log10(Phi_TM_min),log10(Phi_TM_max),num_TM); % number of physical grid points, use simple uniform scale % with fine grid near surface dz = input('Enter interior grid point spacing : '); dz_fine = input('Enter surface (0.9-1.0) spacing : '); %z_inner = [dz : dz : 0.9-dz]; %z_outer = [0.9 : dz_fine : 1.0-dz_fine]; z_grid = [ [dz : dz : 0.9-dz], [0.9 : dz_fine : 1.0-dz_fine] ]; num_grid = length(z_grid); % We now scan the values of the Thiele modulus, starting at the % lowest value. For each value of the Thiele modulus, we need to % solve the set of nonlinear algebraic equations obtained by finite % difference disrectization of the governing PDE. We start at the % lowest value of the Thiele modulus, and use as an initial guess a % uniform concentation profile of 1. In the limit as the Thiele % modulus goes to zero, this initial guess is correct. For each % subsequent calculation, we use the final result of the % previous calculation as an initial guess. % allocate space to store the effectiveness factor eta_eff = zeros(num_beta,num_TM); figure; % iterative over various values of beta for k_beta = 1:num_beta; % form initial guess - uniform concentration phiA_guess = ones(size(z_grid)); % set some options flags for fsolve() options = optimset('LargeScale','off','Jacobian','on'); % iterate over each value of the Thiele modulus for i_TM = 1:num_TM % compute dimensionless profile from Newton's method [phiA,fval,exitflag] = ... fsolve(@catalyst_nonisothermal_calc_f, ... phiA_guess, options, ... Phi_TM(i_TM), beta(k_beta), gamma, z_grid); if(exitflag <= 0) error('fsolve did not converge'); end % compute effectiveness factor eta_eff(k_beta,i_TM) = calc_eta_eff(phiA, ... Phi_TM(i_TM), beta(k_beta), gamma, z_grid); % update initial guess phiA_guess = phiA; end % Now, plot the results semilogx(Phi_TM,eta_eff); gtext(num2str(beta(k_beta))); hold on; end xlabel('\Phi (Thiele modulus)'); ylabel('\eta (effectiveness factor)'); title(['Nonisothermal catalyst: ', ... '\gamma = ', num2str(gamma), ... ', \beta varied']); cpu_end = cputime; cpu_elapsed = cpu_end - cpu_start; disp(['Elapsed CPU time : ', num2str(cpu_elapsed)]); iflag_main = 1; return; % ========================================================= % This routine calculates the function values for the % set of equations that sovle for the dimensionless % concentration profile within the catalyst pellet % for a nonisothermal first order reaction. % K. Beers. MIT ChE. 9/21/2002 function [fval,Jac] = catalyst_nonisothermal_calc_f(phiA, ... Phi_TM, beta, gamma, z_grid); num_grid = length(z_grid); % allocate space for function vector % and Jacobian fval = zeros(size(phiA)); Jac = spalloc(num_grid,num_grid,3*num_grid); % For each point except the first and last, compute % the value of the function. for j=2:(num_grid-1) % estimate the local second derivative in % spherical coordinates z_mid_up = (z_grid(j+1)+z_grid(j))/2; z_mid_lo = (z_grid(j)+z_grid(j-1))/2; dz_mid = z_mid_up - z_mid_lo; dz_up = z_grid(j+1) - z_grid(j); dz_lo = z_grid(j) - z_grid(j-1); A_lo = (z_mid_lo^2)/(dz_lo*dz_mid); A_mid = (-1/dz_mid)*((z_mid_up^2)/dz_up + ... (z_mid_lo^2)/dz_lo); A_up = (z_mid_up^2)/(dz_up*dz_mid); second_deriv = A_lo*phiA(j-1) + A_mid*phiA(j) + ... A_up*phiA(j+1); % compute nonlinear reaction term theta = exp( gamma*beta*(1-phiA(j)) / ... (1 + beta*(1-phiA(j)))); rxn = (z_grid(j)^2)*(Phi_TM^2)*theta*phiA(j); % compute function value fval(j) = second_deriv - rxn; % compute Jacobian elements Jac(j,j-1) = A_lo; Jac(j,j+1) = A_up; dtheta_dphiA = theta* ( ... (-gamma*beta)/(1+beta*(1-phiA(j))) + ... (gamma*beta^2*(1-phiA(j)))/((1+beta*(1-phiA(j)))^2)); drxn_dphiA = (z_grid(j)^2)*(Phi_TM^2) * ... (theta + phiA(j)*dtheta_dphiA); Jac(j,j) = A_mid - drxn_dphiA; end % Now, calculate function value for last point, % employing known concentration at the catalyst % surface. z_mid_up = (1+z_grid(num_grid))/2; z_mid_lo = (z_grid(num_grid) + ... z_grid(num_grid-1))/2; dz_mid = z_mid_up - z_mid_lo; dz_up = 1 - z_grid(num_grid); dz_lo = z_grid(num_grid) - z_grid(num_grid-1); A_lo = (z_mid_lo^2)/(dz_lo*dz_mid); A_mid = (-1/dz_mid)*((z_mid_up^2)/dz_up + ... (z_mid_lo^2)/dz_lo); A_up = (z_mid_up^2)/(dz_up*dz_mid); second_deriv = A_lo*phiA(num_grid-1) + ... A_mid*phiA(num_grid) + A_up; % compute nonlinear reaction term theta = exp( gamma*beta*(1-phiA(num_grid)) / ... (1 + beta*(1-phiA(num_grid)))); rxn = (z_grid(num_grid)^2)*(Phi_TM^2)*theta*phiA(num_grid); % compute function value fval(num_grid) = second_deriv - rxn; % compute Jacobian elements j = num_grid; Jac(j,j-1) = A_lo; dtheta_dphiA = theta* ( ... (-gamma*beta)/(1+beta*(1-phiA(j))) + ... (gamma*beta^2*(1-phiA(j)))/((1+beta*(1-phiA(j)))^2)); drxn_dphiA = (z_grid(j)^2)*(Phi_TM^2) * ... (theta + phiA(j)*dtheta_dphiA); Jac(j,j) = A_mid - drxn_dphiA; % Then, calculate function value for % first point, using symmetry boundary % condition. z_mid_up = (z_grid(2)+z_grid(1))/2; z_mid_lo = (z_grid(1))/2; dz_mid = z_mid_up - z_mid_lo; dz_up = z_grid(2) - z_grid(1); dz_lo = z_grid(1); A_lo = (z_mid_lo^2)/(dz_lo*dz_mid); A_mid = (-1/dz_mid)*((z_mid_up^2)/dz_up + ... (z_mid_lo^2)/dz_lo); A_up = (z_mid_up^2)/(dz_up*dz_mid); second_deriv = (A_mid+4*A_lo/3)*phiA(1) + ... (A_up - A_lo/3)*phiA(2); % compute nonlinear reaction term theta = exp( gamma*beta*(1-phiA(1)) / ... (1 + beta*(1-phiA(1)))); rxn = (z_grid(1)^2)*(Phi_TM^2)*theta*psi(1); % compute function value fval(1) = second_deriv - rxn; % compute Jacobian elements j = 1; Jac(j,j+1) = A_up - A_lo/3; dtheta_dphiA = theta* ( ... (-gamma*beta)/(1+beta*(1-psi(j))) + ... (gamma*beta^2*(1-phiA(j)))/((1+beta*(1-phiA(j)))^2)); drxn_dphiA = (z_grid(j)^2)*(Phi_TM^2) * ... (theta + phiA(j)*dtheta_dphiA); Jac(j,j) = A_mid + 4*A_lo/3; - drxn_dphiA; return; % ======================================================= % This routine computes the effectiveness factor from % the dimensionless concentration profile for a % catalyst particle with a nonisothermal first order % reaction. % K. Beers. MIT ChE. 9/21/2002 function eta_eff = calc_eta_eff(phiA, ... Phi_TM, beta, gamma, z_grid); % compute the augmented z grid including the end % points z_aug = [0, z_grid, 1]; phiA_aug = [0, phiA, 1]; phiA_aug(1) = (4*phiA(1)-phiA(2))/3; % Now, compute on this augmented grid the values % of the integrand. integrand = zeros(size(phiA_aug)); for j=1:length(integrand) var1 = gamma*beta*(1-phiA_aug(j)) / ... (1 + beta*(1-phiA_aug(j))); integrand(j) = 3*phiA_aug(j)*(z_aug(j)^2)*exp(var1); end % Use the trapezoid rule to compute the integral. eta_eff = trapz(z_aug,integrand); return;