% approx_Jacobian_FD.m

%

% function [Jac,iflag] = approx_Jacobian_FD(x,Options,Param);

%

% This MATLAB m-file contains a function that uses finite

% differences to approximate a Jacobian using finite differences.

% The input to the routine is :

%

% x - a column vector of the N unknown variables

% f - the column vector of the function values

% calc_f - the name of the routine that evaluates the function

% Options - a data structure containing the following parameters

%     .epsilon = if non-zero, user-specified offset for each state variable

%                used in the finite difference method.

%     .use_sparse = if non-zero, use sparse matrix format for Jacobian

%     .S = a matrix containing non-zero elements only at those positions

%          for which the Jacobian is sparse

% Param - a data structure containing system parameters to be passed

%         to the function evaluator.

%

% K. Beers. MIT ChE. 10/18/2001

 

 

function [Jac,iflag] = approx_Jacobian_FD(x,f,calc_f,Options,Param);

 

 

% signify sucessful completion not yet attained.

iflag = 0;

 

% extract the number of state variables

Nvar = length(x);

 

 

% Allocate space for the Jacobian in memory based on whether one

% uses the full or sparse matrix format.

 

if(Options.use_sparse)

   

    % extract the number of non-zero elements from S.

    nz_Jac = nnz(Options.S);

   

    % allocate space for Jac using the sparse matrix format

    Jac = spalloc(Nvar,Nvar,nz_Jac);

   

else   % use full matrix format

   

    Jac = zeros(Nvar,Nvar);

   

end

 

 

% We now set the offset used in finite differences for each state variable.

 

if(Options.epsilon==0)   

    epsilon = sqrt(eps);

    epsilon_is_vector = 0;

   

elseif (length(Options.epsilon)==1)   

    epsilon = Options.epsilon;

    epsilon_is_vector = 0;

   

else   

    epsilon = Options.epsilon;

    epsilon_is_vector = 1;

 

end

 

 

% Begin iterations over each state variable to estimate corresponding

% elements of the Jacobian by finite differences.

 

 

for ivar = 1:Nvar

       

    % Get magnitude of offfset of unknown ivar

    if(epsilon_is_vector)

        delta_ivar = epsilon(ivar);

    else

        delta_ivar = epsilon;

    end

   

    % Get offset state vector.

    x_offset = x;

    x_offset(ivar) = x_offset(ivar) + delta_ivar;

   

    % Calculate function vector for offset state vector.

    f_offset = feval(calc_f,x_offset,Param);

   

    % Calculate the Jacobian elements in column ivar.

    if(Options.use_sparse==0)

        Jac(:,ivar) = (f_offset - f)/delta_ivar;       

    else

        list_nz = find(Options.S(:,ivar));

        for count=1:length(list_nz)

           

            % Get row number of non-zero element.

            k = list_nz(count);

           

            % calculate Jacobian element at this position

            Jac(k,ivar) = (f_offset(k) - f(k))/delta_ivar;

           

        end

    end

 

end

 

iflag = 1;

 

return;