7.1 Algebraic Loops and S-functions

A frequently asked question about SIMULINK, is ''What are algebraic loops and how are they solved?'' This issue often comes up in the context of S-functions and how the direct feedthrough flag affects the behavior of the SIMULINK system. These issues are addressed in this technical note. Consider the following system (Figure 1).

This system contains an algebraic loop. An algebraic loop is formed when two or more blocks with direct feedthrough (the output of the block at time t, is a function of the input at time t) form a feedback loop. The basic problem with algebraic loops is that the output, y, at time, t, is a function of itself. For the system shown in Figure 1,

y(t) = K1*u(t) - K1*K2*y(t)
In general, SIMULINK solves algebraic loops as follows: At each time, t, SIMULINK assumes an output value of

yguess = y[t-1]
(i.e., the initial guess for y at the current integration step is equal to the value at the previous integration step, yold). The current calculated output of the K1 Gain block is then computed as,

ycalc = K1*u - K1*K2*yguess
If ycalc = yguess, then yguess is accepted as the output, y, at time t. If ycalc != yguess, then an iterative Newton-Raphson technique (see "Numerical Methods For Mathematics, Science, and Engineering," by John H. Mathews; published by Prentice Hall for information regarding the Newton Raphson technique) is used to modify yguess until either the solution converges (within some tolerance) or the maximum number of iterations has been reached. The maximum number of iterations, 200, is hard-coded into SIMULINK.

The closed loop transfer function for this system is:

H(s) = K1/(1 + K1*K2 ) = 1/(1+1*1) = 1/2 = 0.5 
With a constant input of 1, the output is a constant of 0.5. Run the model to verify that SIMULINK is solving the loop correctly.

For a simple case, in which the closed loop transfer function is simply a ratio of gains, you may ask, "Why use the above described iterative technique when there is simple closed form solution?" The answer to this question is that the example system shown above is a special case that is "looked for" by SIMULINK. For this case, SIMULINK actually replaces the feedback loop with the closed loop gain of 0.5. This solution is much more efficient than the iterative technique used to solve the more general case.

Replace the gain K1 (see Figure 2), with the following S-function to examine the behavior of S-functions with direct feedthrough (see the Advanced Topics Section of the SIMULINK User's Guide for more information regarding S-functions).

---------------------- SGAIN.M ----------------------

function [sys,x0] = sgain(t,x,u,flag)
if flag == 0,
   sys = [0 0 1 1 0 1];    % sys(6) is the direct
                           % feedthrough flag
   x0 = [];
elseif abs(flag) == 3,
   sys = u;                % sys in flag 3 (the output)
                           % involves u => direct
                           % feedthrough
else
   sys = []; 
end 
If an S-function is meant to implement direct feedthrough (i.e., the output of a block at time t depends on the input at time t), then the direct feedthrough flag, sys(6), in the flag == 0 section of the S-function must be set to 1. If this flag is not set to 1, then the algebraic loop solver will not be invoked! Run the simulation to verify that this S-function is equivalent to the Gain block K1.

It is interesting to note that calling the model from the command line with flag 3, yields the correct results (i.e., the algebraic loop is solved). The syntax for an example call is as follows:

>> tmp = loop( 0,[],[],3)     % the result, as expected, is 0.5 
ans = 0.5
Please note that the "Outport" is required to get results in this fashion.

Let's examine the effects of setting the direct feedthrough flag to 0. This effectively breaks the algebraic loop, introducing a delay of one integration step. The initial value of y is taken as zero. Running the model with a min and max step size of 1, and return variables, [t,x,y], for five seconds yields the following results:

>> [t y]
1     0
1     1
2     0
3     1
4     0
5     1
The algebraic loop is no longer solved, or more precisely, the algebraic loop no longer exists. The output, y, is:

y[t] = K1*u - K1*K2*y[t-1],
where y[t -1] is the output at the time of the previous integration step.

Calling the overall system from the command line not only reveals that the algebraic loop is no longer solved, but also reveals some unexpected behavior. Repeated calls of:

>> tmp = loop(0,[],[],3);
%tmp = 0 
>> tmp = loop(0,[],[],3);
%tmp = 1 
>> tmp = loop(0,[],[],3);
%tmp = 0 
...
result in inconsistent output in SIMULINK v1.x (this behavior will change in future versions). When the model is called in this manner, the output vector is not re-initialized in between calls. For the case of this simple, state-less model, the result of repeated calls with flag = 3 is to step through the simulation (i.e., issuing the above command 5 times yields identical results to simulating the model with a min and max step size of 1,for five seconds). Calling the system with flag 0 causes the output buffer to be flushed and consequently yields the expected result. Thus, repeated calls of:

>> tmp = Untitled(0,[],[],3), Untitled([],[],[],0); 
yield the consistent result of zero.

(c) Copyright 1994 by The MathWorks, Inc.