%  CLOSED LOOP FREQUENCY RESPONSE

%  FILENAME: BODECL.M
%  DATE: October 1994
%  VERSION: 02
%  COPYRIGHT 1993, 1994 M.Gretzinger & T.Marlin
%            McMaster University   

% This m-file is called from STABLE.M. It sets up a menu to enable the user
%       to specify the start and end frequency, set point or disturbance 
%       and plot the amplitude ratio of the transfer function, using the 
%       parameters specified by the process, disturbance and tuning data.
%       For the disturbance response, the user has the option to have the 
%       disturbance and process dynamics the same, or to specify unique 
%       disturbance dynamics in the disturbance menu.

while 1
  clc
  disp('*************************************************************')
  disp('*           CLOSED LOOP FREQUENCY RESPONSE                  *')
  disp('*                                                           *')
  disp('*************************************************************')
  disp('')
  disp('SELECT THE APPROPRIATE MENU ITEM')
  disp('')
  disp('MODIFY...')
  disp('                                    PRESENT VALUES')
  fprintf('1) Lowest Frequency                 %4.5g\n',wbegin)
  fprintf('2) Highest Frequency                %4.2f\n',wstop)
  if responsetype == 's'
      disp('3) Select Set Point or Disturbance    s')
  else
      disp('3) Select Set Point or Disturbance    d')
  end
  disp('4) Create Bode plot')
  disp('5) Return to main menu')
  disp('')
        
  m6 = input('Enter the desired selection:   ');
  
  if isempty(m6), break, end
      
  m6 = round(m6);
  if (m6<1) | (m6>5)
      disp('')
      disp('Not a valid selection')
      disp('')
      disp('Press ENTER to continue')
      pause;
  end    
  
  if m6 == 1
       junkwbegin = input('Enter value for lowest frequency:  ') ;
       if isempty(junkwbegin)
           junkwbegin = wbegin ;
       end
       if junkwbegin >= wstop
          junkwbegin = wbegin;
          disp(' illegal entry, > highest')
          disp(' press enter to continue')
          pause
       end
       wbegin = junkwbegin;


  elseif m6 == 2
       junkwstop = input('Enter value for highest frequency:  ') ;
       if isempty(junkwstop)
           junkwstop = wstop  ;
       end
       if junkwstop <= wbegin
           junkwstop = wstop;
           disp ('illegal entry, < lowest')
           disp ('press enter to continue')
           pause
       end
       wstop = junkwstop;

  elseif m6 == 3
       disp('For set point, enter the letter:    s')
       disp('For disturbance, enter the letter:  d')
       disp('')
       junktype = input('Selection:  ','s') ;
       if junktype ~= 's' & junktype ~= 'd'
          junktype = responsetype;
          disp (' illegal entry, please reenter ')
          disp (' press enter to continue')
          pause
       end
       if isempty(junktype)
           junktype = 'd' ;
       end
       responsetype = junktype;

  elseif m6 == 4

       if responsetype == 'd'
          answer = input('Are disturbance dynamics same as process dynamics? [y/n]  ','s');
          if answer ~= 'y' & answer ~= 'n'
             answer = 'y';
          end
          if answer == 'y'
             thetad = theta; taulead_d = taulead; 
             taud1 = tau1; taud2 = tau2; taud3 = tau3; xid = xi;
          elseif answer == 'n'
             thetad = 0; taulead_d = 0; 
             taud1 = taudist;  taud2 = 0; taud3 = 0; xid = 0;
          end
       end

       % Block to calculate transfer function (disturbance or set point), 
       % and amplitude ratio over the chosen frequency range. A vector of 
       % frequencies, called w, is defined using logspace. The vector of 
       % 500 frequencies are evenly spaced in the log domain between 
       % wbegin and wstop. Each element in the vector is then multiplied 
       % by jj to create the vector s. The vectors gp, gc and G 
       % are then calculated. Elementwise multiplication(.*), division(./) 
       % and powers(.^) are used in order that the expressions for gp, gc 
       % and G are carried out once for each element in the vectors making 
       % up the expressions.
           
       jj = sqrt(-1) ;
       w = logspace(log10(wbegin), log10(wstop), 500) ;
       s = jj*w ;
              
       gp = kp*exp(-theta*s).*(taulead*s + 1)...
             ./((tau1*s + 1).*(tau2*s + 1).*(tau3^2*s.^2 + 2*xi*tau3*s + 1));

       gd = kpd*exp(-thetad*s).*(taulead_d*s + 1)...
         ./((taud1*s + 1).*(taud2*s + 1).*(taud3^2*s.^2 + 2*xid*taud3*s + 1));
           
       % If block to prevent division by zero which would occur when
       % there is no integral mode.
       if ti == 0
          gc = kc*(1 + td*s) ;
       else
          gc = kc*(1 + (ti*s).^(-1) + td*s) ;
       end

      % If block to calculate the closed loop transfer function, 
      % depending on whether set point or disturbance is chosen.
       if responsetype == 's'
          G = gp.*gc./(1 + gp.*gc) ;
       elseif responsetype == 'd'
          G = gd./(1 + gp.*gc) ;
       end
           
      % Calculate the vector of amplitude ratios of G. The function ANGLE
      % calculates the amplitude ratios of each of the complex numbers 
      % in the vector G.
       ar = abs(G) ;
           
      % Create amplitude ratio plot
       clf ; axis('auto')
       loglog(w, ar)
       title('CLOSED-LOOP BODE PLOT')
       xlabel('Frequency, w  (rad/time)')
       ylabel('Amplitude Ratio')
       figure (1)
       pause

       close all
       clear w s gp gd gc G ar

  else
       break
  end        % if m6   (line )
  
end    % while 1 (line )

