S-funkcia je dynamický blok v Simulinku, ktorého "opis" je definovaný vo funkcii-súbore vytvoreného v MATLABe, v jazykoch C, C++, Ada, alebo Fortran. S-funkcie vytvorené v jazykoch C, C++, Ada a Fortran sú kompilované na MEX-súbory (pozri "Building MEX-Files" v dokumentácii). My sa budeme venovať S-funkciam vytvoreným v MATLABe.
S-funkcia umožňuje užívateľovi vytvárať vlastné bloky do modelu v Simulinku. V m-súbore S-funkcie môžu byť definované vlastné diferenciálne rovnice (ordinary differential equations (ODEs)), rovnice diskrétneho systému a/alebo ľubovoľný typ algoritmu.

Obr. 1. Blok S-function
Do položky S-function parameters sa zadávajú parametre "prenášané" do S-funkcie. Jednotlivé parametre sa oddeľujú čiarkou. Parametrami môžu byť konštanty (vektory, matice), názvy premenných definovaných v pracovnom priestore MATLABu, alebo výrazy v MATLABe (obr. 1). Parametre t,x,u (čas, stavy, vstupy) sú Simulinkom automaticky "prenášané" do S-funkcie.
S-funkcia reprezentuje dynamický blok
u -> [ x ] -> y vstup systém (stavy) výstup
kde výstupy sú funkciou periódy vzorkovania, vstupov a stavov. Matematické vzťahy medzi vstupmi, výstupmi a stavmi môžu byť vyjadrené nasledujúcimi rovnicami:
y = f_y(t,x,u) (výstup)
x_s = f_s(t,x,u) (derivácia - spojitý systém)
x_d(t+1) = f_d(t,x,u) (diferencia - diskrétny systém)
x = {x_s, x_d}
"Spracovanie/simulácia" S-funkcie prebieha v niekoľkých etapách:
S-funkcia v tvare m-súboru je definovaná ako obyčajná funkcia v MATLABe:
function [sys,x0,str,ts] = meno(t,x,u,flag)
V prípade, že S-funkcia vyžaduje ďalšie vstupné parametre, jej tvar je nasledujúci:
function [sys,x0,str,ts] = meno(t,x,u,flag,p1,p2,...)
kde meno je názov S-funkcie, t je aktuálny čas, x je vektor stavov daného bloku (S-funkcie), u sú vstupy do bloku, flag udáva vykonávanú úlohu a p1, p2, ... sú parametre bloku. Počas simulácie modelu, Simulink opakovane vyvoláva S-funkciu meno a na základe flagov sa vykonávajú jednotlivé etapy S-funkcie.
Poznámka: v adresári toolbox\simulink\blocks\ sa nachádzajú príklady spojitej (csfunc.m) a diskrétnej (dsfunc.m) s-funkcie
Štruktúra S-funkcie bude vysvetlená na príklade šablóny sfuntmpl.m (help sfuntmpl, type sfuntmpl):
function [sys,x0,str,ts] = sfuntmpl(t,x,u,flag)
switch flag,
%%%%%%%%%%%%%%%%%%
% Initialization %
%%%%%%%%%%%%%%%%%%
case 0,
[sys,x0,str,ts]=mdlInitializeSizes;
%%%%%%%%%%%%%%%
% Derivatives %
%%%%%%%%%%%%%%%
case 1,
sys=mdlDerivatives(t,x,u);
%%%%%%%%%%
% Update %
%%%%%%%%%%
case 2,
sys=mdlUpdate(t,x,u);
%%%%%%%%%%%
% Outputs %
%%%%%%%%%%%
case 3,
sys=mdlOutputs(t,x,u);
%%%%%%%%%%%%%%%%%%%%%%%
% GetTimeOfNextVarHit %
%%%%%%%%%%%%%%%%%%%%%%%
case 4,
sys=mdlGetTimeOfNextVarHit(t,x,u);
%%%%%%%%%%%%%
% Terminate %
%%%%%%%%%%%%%
case 9,
sys=mdlTerminate(t,x,u);
%%%%%%%%%%%%%%%%%%%%
% Unexpected flags %
%%%%%%%%%%%%%%%%%%%%
otherwise
error(['Unhandled flag = ',num2str(flag)]);
end
% end sfuntmpl
%
%==========================================================================
% mdlInitializeSizes
% Return the sizes, initial conditions, and sample times for the S-function.
%==========================================================================
%
function [sys,x0,str,ts]=mdlInitializeSizes
%
% call simsizes for a sizes structure, fill it in and convert it to a
% sizes array.
%
% Note that in this example, the values are hard coded. This is not a
% recommended practice as the characteristics of the block are typically
% defined by the S-function parameters.
%
sizes = simsizes;
sizes.NumContStates = 0;
sizes.NumDiscStates = 0;
sizes.NumOutputs = 0;
sizes.NumInputs = 0;
sizes.DirFeedthrough = 1;
sizes.NumSampleTimes = 1; % at least one sample time is needed
sys = simsizes(sizes);
%
% initialize the initial conditions
%
x0 = [];
%
% str is always an empty matrix
%
str = [];
%
% initialize the array of sample times
%
ts = [0 0];
% end mdlInitializeSizes
%
%==========================================================================
% mdlDerivatives
% Return the derivatives for the continuous states.
%==========================================================================
%
function sys=mdlDerivatives(t,x,u)
sys = [];
% end mdlDerivatives
%
%==========================================================================
% mdlUpdate
% Handle discrete state updates, sample time hits, and major time step
% requirements.
%==========================================================================
%
function sys=mdlUpdate(t,x,u)
sys = [];
% end mdlUpdate
%
%==========================================================================
% mdlOutputs
% Return the block outputs.
%==========================================================================
%
function sys=mdlOutputs(t,x,u)
sys = [];
% end mdlOutputs
%
%==========================================================================
% mdlGetTimeOfNextVarHit
% Return the time of the next hit for this block. Note that the result is
% absolute time. Note that this function is only used when you specify a
% variable discrete-time sample time [-2 0] in the sample time array in
% mdlInitializeSizes.
%==========================================================================
%
function sys=mdlGetTimeOfNextVarHit(t,x,u)
sampleTime = 1; % Example, set the next hit to be one second later.
sys = t + sampleTime;
% end mdlGetTimeOfNextVarHit
%
%==========================================================================
% mdlTerminate
% Perform any end of simulation tasks.
%==========================================================================
%
function sys=mdlTerminate(t,x,u)
sys = [];
% end mdlTerminate
Definovanie periódy vzorkovania: (ts)
ts = [0 0] (spojitý systém) ts = [-1 0] (zdedená ts, offset) ts = [1 0] (diskrétny systém, ts = 1) ts = [0 0; 1 0] (hybridny systém (spojitý + diskrétny systém))
Pri zdedenej perióde vzorkovania sa perióda vzorkovania "dedí" z predchádzajúceho, alebo nasledujúceho bloku, alebo je použitá najrýchlejšia perióda vzorkovania.
Definovanie počiatočných hodnôt stavov: (x0)
x0 = [] (systém nemá stavy) x0 = zeros(1,n) (systém má n stavov ( = 0)) % length(x0) = length(sizes.NumContStates) (spojitý systém) % length(x0) = length(sizes.NumDiscStates) (diskrétny systém)
Definovanie veľkosti vstupov/výstupov: (sizes.NumOutputs, sizes.NumInputs)
sizes.NumOutputs = 0; (nie je výstup) sizes.NumInputs = 0; (nie je vstup) sizes.NumOutputs = 2; (2 výstupy) sizes.NumInputs = 3; (3 vstupy) sizes.NumOutputs = -1; (výstupy s dynamickou veľkosťou) sizes.NumInputs = -1; (vstupy s dynamickou veľkosťou) % veľkosť vektora vstupu (sizes.NumInputs = length(u))
Definovanie priamej väzby (Direct feedthrough): (sizes.DirFeedthrough)
sizes.DirFeedthrough = 0; sizes.DirFeedthrough = 1;
sizes.DirFeedthrough = 1 znamená, že výstup (flag == 3) alebo premenlivá perióda vzorkovania (flag == 4) je priamo funkciou vstupu (u), inak sizes.DirFeedthrough = 0.
Definovanie sizes.NumSampleTimes:
Ak sizes.NumSampleTimes > 0, potom S-funkcia má "block-based sample times".
Postup tvorby S-funkcie bude vysvetlený na príklade modelu hydraulického systému popísaného diferenciálnymi rovnicami (rovnice sú zapísané vo formáte TeX):
\dot{h}_1 = 1/F1 u - k1/F1 sqrt ( h(1) - h(2) )
\dot{h}_2 = k1/F2 sqrt ( h(1) - h(2) ) - k2/F2 sqrt ( h(2) )
function [sys,x0,str,ts] = hyd2(t,x,u,flag)
switch flag,
case 0,
[sys,x0,str,ts]=mdlInitializeSizes;
case 1,
sys=mdlDerivatives(t,x,u);
case 3,
sys=mdlOutputs(t,x,u);
case {2, 4, 9},
sys = [];
otherwise
error(['Unhandled flag = ',num2str(flag)]);
end
%==========================================================================
% mdlInitializeSizes
%==========================================================================
function [sys,x0,str,ts]=mdlInitializeSizes
h1s=1; h2s=1; % definovanie ustálených výšok hladín
sizes = simsizes;
sizes.NumContStates = 2; % dva stavy (výška h1 a h2)
sizes.NumDiscStates = 0;
sizes.NumOutputs = 1; % jeden výstup (výška h2)
sizes.NumInputs = 1; % jeden vstup (prietok)
sizes.DirFeedthrough = 0;
sizes.NumSampleTimes = 1;
sys = simsizes(sizes);
x0 = [h1s; h2s];
str = [];
ts = [0 0];
%==========================================================================
% mdlDerivatives
%==========================================================================
function sys=mdlDerivatives(t,x,u)
f1=1; f2=1; k1=1; k2=1; % definovanie parametrov zásobníkov
% Matematický model hydraulického systému v tvare diferenciálnych rovníc
sys(1) = 1/f1*u-k1/f1*sqrt(x(1)-x(2));
sys(2) = k1/f2*sqrt(x(1)-x(2))-k2/f2*sqrt(x(2));
sys = [sys(1); sys(2)];
%==========================================================================
% mdlOutputs
%==========================================================================
function sys=mdlOutputs(t,x,u)
sys = x(2); % Výstupom je druhý stav (výška h2)
V S-funkcii hyd2.m sú parametre f1,f2,k1,k2,h1s,h2s definované priamo.

Obr. 2. S-funkcia hyd2.m s priamo definovanými parametrami
V nasledujúcej funkcii sa parametre f1,f2,k1,k2,h1s,h2s funkcii predávajú.
function [sys,x0,str,ts] = hyd2m(t,x,u,flag,ff,kk,hs)
switch flag,
case 0,
[sys,x0,str,ts]=mdlInitializeSizes(hs(1),hs(2));
case 1,
sys=mdlDerivatives(t,x,u,ff(1),ff(2),kk(1),kk(2));
case 3,
sys=mdlOutputs(t,x,u);
case {2, 4, 9},
sys = [];
otherwise
error(['Unhandled flag = ',num2str(flag)]);
end
%==========================================================================
% mdlInitializeSizes
%==========================================================================
function [sys,x0,str,ts]=mdlInitializeSizes(h1s,h2s)
sizes = simsizes;
sizes.NumContStates = 2;
sizes.NumDiscStates = 0;
sizes.NumOutputs = 1;
sizes.NumInputs = 1;
sizes.DirFeedthrough = 0;
sizes.NumSampleTimes = 1;
sys = simsizes(sizes);
x0 = [h1s; h2s];
str = [];
ts = [0 0];
%==========================================================================
% mdlDerivatives
%==========================================================================
function sys=mdlDerivatives(t,x,u,f1,f2,k1,k2)
sys(1) = 1/f1*u-k1/f1*sqrt(x(1)-x(2));
sys(2) = k1/f2*sqrt(x(1)-x(2))-k2/f2*sqrt(x(2));
sys = [sys(1); sys(2)];
%==========================================================================
% mdlOutputs
%==========================================================================
function sys=mdlOutputs(t,x,u)
sys = x(2);

Obr. 3. Nemaskovaná S-funkcia hyd2m

Obr. 4. Maskovaná S-funkcia hyd2m
Demoverzia S-funkcie, ktorej výstup je dvojnásobkom jej vstupu (y = 2 * u).
function [sys,x0,str,ts] = timestwo(t,x,u,flag)
switch flag,
case 0
[sys,x0,str,ts]=mdlInitializeSizes;
case 3
sys=mdlOutputs(t,x,u);
case { 1, 2, 4, 9 }
sys=[];
otherwise
error(['Unhandled flag = ',num2str(flag)]);
end
%==========================================================================
% mdlInitializeSizes
%==========================================================================
function [sys,x0,str,ts] = mdlInitializeSizes()
sizes = simsizes;
sizes.NumContStates = 0;
sizes.NumDiscStates = 0;
sizes.NumOutputs = -1; % dynamically sized
sizes.NumInputs = -1; % dynamically sized
sizes.DirFeedthrough = 1; % has direct feedthrough
sizes.NumSampleTimes = 1;
sys = simsizes(sizes);
str = [];
x0 = [];
ts = [-1 0]; % inherited sample time
%==========================================================================
% mdlOutputs
%==========================================================================
function sys = mdlOutputs(t,x,u)
sys = u * 2;

Obr. 5. Model s S-funkciou timestwo.m

Obr. 6. Priebeh simulácie s S-funkciou timestwo.m
Matematický model zásobníkov kvapaliny s interakciou
dh1/dt = 1/F1 * q0 - k1/F1 * (h1 - h2)0.5
dh2/dt = k1/F2 * (h1 - h2)0.5 - k2/F2 * (h2)0.5
Matematický model zásobníkov kvapaliny bez interakcie
dh1/dt = 1/F1 * q0 - k1/F1 * (h1)0.5
dh2/dt = k1/F2 * (h1)0.5 - k2/F2 * (h2)0.5
Poznámka: začiatočné hodnoty výšok hladín závisia od typu (s/bez interakcie).