% ice_root.m % Adapt ice_root.m to do calculations for your problem sets. % ice_root calculates the RGA (relative gain array) and DC (disturbance % cost) for the 10.492 heat exchanger network % Run ice_root from the Matlab command line. Its use requires that a % column vector called "xguess" be available in memory, and that 3 files % be available in the user's directory: % reduced_Newton.m - presented by Prof. Beers in 10.34, it applies the % Newton-Raphson method (with some embellishments) to find the root of a % system of nonlinear algebraic equations. It has been modified for % 10.492, and should need no further attention from the user. % calc_f.m - calculates the system of equations, given a guess of the root. % When calc_f.m returns a vector of zeroes, the root has been found. % calc_f.m is used by reduced_Newton.m. The user should modify the % calc_f.m template to contain the network equations. Any parameters % that are to be held constant (such as Cp and U) may be set there. % calc_Jac.m - calculates the Jacobian matrix (multidimensional slope) of % the equation system in calc_f.m. It should need no modification by the % user. disp ('********** Computations for the 10.492 HX Network *************') % set up the rootfinding parameters in a data structure % their significance is described in the reduced_Newton.m file Options.max_iter = 200; Options.max_iter_LS = 200; Options.rtol = 1; Options.atol = 1.e-5; Options.step_tol = 1.e-3; Options.verbose = 1; Options.use_range = 0; Options.range = 0; disp ('The control parameters for root-finding routine reduced_Newton.m') disp (Options) % set up the numerical differentiation spacing % dy/dx ~ (y((1+xdiff)*x) - y((1-xdiff)*x))/(2*x*xdiff) % vary this value in repeated runs to check whether the calculated % derivatives are sensitive to the value chosen for xdiff xdiff = 0.01; disp ('The differentiation interval as a percentage of the ref value') disp (xdiff) %determine whether the user should form the column vector that contains the %initial guess if exist('xguess') == 0 disp ('You must first define the initial guess column vector "xguess"') disp ('The length of xguess must be consistent with calc_f.m') return end % determine whether the structure Param exists. % if so, use it, because the user may wish to modify it from the command % line. % if not, create it here if exist('Param') == 0 Param.w1 = 8.2; Param.w2 = 9.1; Param.w3 = 5.6; Param.T1 = 250; Param.T2 = 136; Param.T3 = 100; end % set the manipulated variable reference conditions w2r = Param.w2; w3r = Param.w3; disp ('Manipulated variable reference values') w2r, w3r % set the disturbance variable reference conditions w1r = Param.w1; T1r = Param.T1; T2r = Param.T2; T3r = Param.T3; disp ('Disturbance variable reference values') w1r, T1r, T2r, T3r % prepare linear system matrices % set the matrix dimensions according to the numbers of variables Pm = zeros(3,2); % 3 CV; 2 MV Pd = zeros(3,4); % 3 CV; 4 DV % prepare scaling matrices for the variables % insert appropriate scaling ranges as required for individual variables S = 2*blkdiag(10, 10, 10); % all temperatures at +/- 10 deg C Sm = 2*blkdiag(w2r, w3r); % all flows at +/- the reference value Sd = 2*blkdiag(w1r, 10, 10, 10); % prepare a summary matrix to hold DC calculations % its length is number-of-values ^ number-of-dist-variables % its width is 1 + number-of-dist-variables + number-of-manip-variables DC_summary = zeros(81,7); % Section 1: calculate the reference condition CV from the % reference DV and MV % ---------------------------------------------------------------- % call reduced_Newton to find the root satisfying the variables of Param [xref,iflag,iter_conv,x_traj,f_traj] = ... reduced_Newton(xguess,@calc_f,@calc_Jac,Options,Param); % display output disp ('Calculation of the Reference Case') disp ('number of iterations'); disp(iter_conv) % if this reference case is satisfactorily converged, the other % calculations, which are conducted nearby, are likely to be successful. % for normal convergence, clean up imaginary components that may have % arisen during root-finding. % leave them to attract attention otherwise. if iflag == 1 disp ('convergence normal') xref = real(xref); else disp ('did not converge; run with improved guess') end % xref is the reference case root; ensure that the definition is % consistent between this program and calc_f.m disp ('controlled variables T6r T8r T9r'); disp(xref(1:3)) disp ('intermediate variables T4r T5r T7r'); disp (xref(4:6)) % Section 2: calculate matrix Pm by successive perturbation of the % manipulated variables. Each differentiation calculates one column of Pm. % ----------------------------------------------------------- % w/r/t MV W2 Param.w2 = w2r*(1+xdiff); %positive perturbation of w2 [rootplus,iflag,iter_conv,x_traj,f_traj] = ... reduced_Newton(xref,@calc_f,@calc_Jac,Options,Param); Param.w2 = w2r*(1-xdiff); %negative perturbation of w2 [rootminus,iflag,iter_conv,x_traj,f_traj] = ... reduced_Newton(xref,@calc_f,@calc_Jac,Options,Param); Pm(1:3,1) = (rootplus(1:3)-rootminus(1:3))/(2*xdiff*w2r); Param.w2 = w2r; %return w2 to reference value % w/r/t MV W3 Param.w3 = w3r*(1+xdiff); [rootplus,iflag,iter_conv,x_traj,f_traj] = ... reduced_Newton(xref,@calc_f,@calc_Jac,Options,Param); Param.w3 = w3r*(1-xdiff); [rootminus,iflag,iter_conv,x_traj,f_traj] = ... reduced_Newton(xref,@calc_f,@calc_Jac,Options,Param); Pm(1:3,2) = (rootplus(1:3)-rootminus(1:3))/(2*xdiff*w3r); Param.w3 = w3r; disp (' ') disp ('The matrix Pm') disp (Pm) % Section 3: calculate matrix Pd by successive perturbation of the % disturbance variables. Each differentiation calculates one column of Pd. % ----------------------------------------------------------- % w/r/t DV W1 Param.w1 = w1r*(1+xdiff); [rootplus,iflag,iter_conv,x_traj,f_traj] = ... reduced_Newton(xref,@calc_f,@calc_Jac,Options,Param); Param.w1 = w1r*(1-xdiff); [rootminus,iflag,iter_conv,x_traj,f_traj] = ... reduced_Newton(xref,@calc_f,@calc_Jac,Options,Param); Pd(1:3,1) = (rootplus(1:3)-rootminus(1:3))/(2*xdiff*w1r); Param.w1 = w1r; % w/r/t DV T1 Param.T1 = T1r*(1+xdiff); [rootplus,iflag,iter_conv,x_traj,f_traj] = ... reduced_Newton(xref,@calc_f,@calc_Jac,Options,Param); Param.T1 = T1r*(1-xdiff); [rootminus,iflag,iter_conv,x_traj,f_traj] = ... reduced_Newton(xref,@calc_f,@calc_Jac,Options,Param); Pd(1:3,2) = (rootplus(1:3)-rootminus(1:3))/(2*xdiff*T1r); Param.T1 = T1r; % w/r/t DV T2 Param.T2 = T2r*(1+xdiff); [rootplus,iflag,iter_conv,x_traj,f_traj] = ... reduced_Newton(xref,@calc_f,@calc_Jac,Options,Param); Param.T2 = T2r*(1-xdiff); [rootminus,iflag,iter_conv,x_traj,f_traj] = ... reduced_Newton(xref,@calc_f,@calc_Jac,Options,Param); Pd(1:3,3) = (rootplus(1:3)-rootminus(1:3))/(2*xdiff*T2r); Param.T2 = T2r; % w/r/t DV T3 Param.T3 = T3r*(1+xdiff); [rootplus,iflag,iter_conv,x_traj,f_traj] = ... reduced_Newton(xref,@calc_f,@calc_Jac,Options,Param); Param.T3 = T3r*(1-xdiff); [rootminus,iflag,iter_conv,x_traj,f_traj] = ... reduced_Newton(xref,@calc_f,@calc_Jac,Options,Param); Pd(1:3,4) = (rootplus(1:3)-rootminus(1:3))/(2*xdiff*T3r); Param.T3 = T3r; disp (' ') disp ('The matrix Pd') disp (Pd) % Section 4: scale the coefficient matrices % --------------------------------------------------------- disp (' ') disp ('The scaled coefficient matrices') Pmstar = S\Pm*Sm Pdstar = S\Pd*Sd % Section 5: calculate RGA % because we have only 2 MV for 3 CV, we must calculate several % combinations. % separate cases would be unnecessary for balanced CV and MV % ----------------------------------------------------------- % case 1: control T6 and T8 disp ('control T6 and T8') Pmcase = Pm(1:2,:) % select appropriate rows RGA = Pmcase.*inv(Pmcase)' % case 2: control T6 and T9 disp ('control T6 and T9') Pmcase = [Pm(1,:);Pm(3,:)] % select appropriate rows RGA = Pmcase.*inv(Pmcase)' % case 3: control T8 and T9 disp ('control T8 and T9') Pmcase = Pm(2:3,:) % select appropriate rows RGA = Pmcase.*inv(Pmcase)' % Section 6: calculate DC % case 3 has been selected for calculating DC; this, of course, required % coding this section after preliminary runs had been made of the RGA. % ---------------------------------------------------------------- % select the subset of Pmstar and Pdstar to use for DC Pmsel = Pmstar(2:3,:); Pdsel = Pdstar(2:3,:); % calculate the quotient of Pdsel and Pmsel Pquo = Pmsel\Pdsel; % set disturbance limits (add variables as required) xd1 = [ -0.25 0 0.25 ]; % variable w1 xd2 = [ -0.5 0 0.5 ]; % variable T1 xd3 = [ -0.5 0 0.5 ]; % variable T2 xd4 = [ -0.5 0 0.5 ]; % variable T3 % loop to calculate combinations of the DV (add loops as required) case_num = 0; for i1 = 1:3 %perturb variable xd1 for i2 = 1:3 %perturb variable xd2 for i3 = 1:3 %perturb variable xd3 for i4 = 1:3 %perturb variable xd4 case_num = case_num+1; xdstar = [xd1(i1); xd2(i2); xd3(i3); xd4(i4)]; xmstar = -Pquo*xdstar; DC = norm(xmstar); DC_summary (case_num,:) = [DC xdstar' xmstar']; end end end end % find the maximum DC DC_sort = sortrows(DC_summary); disp ('largest values of Disturbance Cost') disp (' DC Dist_Variables Manip_Variables') length = size(DC_sort,1); disp (DC_sort ((length-5):length,:)) % Section 7: at the maximum DC % examine the required manipulated variable capacity, and compare % the linear and nonlinear models at the extreme disturbance values % ---------------------------------------------------------------- % compose a vector of disturbance variables at the worst DC xdstar_max = DC_sort(length,2:5)'; % compose a vector of manipulated variables at this condition xmstar_pc = DC_sort(length,6:7)'; % compute the controlled variables via the linear model ystar_pc = Pmstar*xmstar_pc + Pdstar*xdstar_max; % convert to deviation variables for output y_pc = S*ystar_pc; disp ('controlled variable deviation at worst disturbance - linear model (degC)') disp (y_pc) %convert the DV (max) and MV (pc) to deviation variables xd_max = Sd*xdstar_max; xm_pc = Sm*xmstar_pc; % set the Param structure to the extreme conditions Param.w1 = xd_max(1) + w1r; Param.w2 = xm_pc(1) + w2r; Param.w3 = xm_pc(2) + w3r; Param.T1 = xd_max(2) + T1r; Param.T2 = xd_max(3) + T2r; Param.T3 = xd_max(4) + T3r; % compute the controlled variables via the nonlinear model [y_nonlin,iflag,iter_conv,x_traj,f_traj] = ... reduced_Newton(xref,@calc_f,@calc_Jac,Options,Param); % express nonlinear output as deviation variables y_pcnl = zeros(3,1); y_pcnl(1) = y_nonlin(1) - xref(1); y_pcnl(2) = y_nonlin(2) - xref(2); y_pcnl(3) = y_nonlin(3) - xref(3); disp ('controlled variable deviation at worst disturbance - nonlinear model (degC)') disp (y_pcnl(1:3)) % return Param to reference values in case user wishes further runs Param.w1 = w1r; Param.w2 = w2r; Param.w3 = w3r; Param.T1 = T1r; Param.T2 = T2r; Param.T3 = T3r; % express manipulated variable in physical form xm_req(1) = xm_pc(1) + w2r; xm_req(2) = xm_pc(2) + w3r; disp ('check that manipulated variable motion is not extreme') disp ('w2 (kg s-1)'); disp (xm_req(1)) disp ('w3 (kg s-1)'); disp (xm_req(2)) % Dr. Barry S. Johnston, Copyright 2004.