s-function和 matlab function是应用极为广泛的模块,通过s-function利用导数定义求导数,可将此模块应用于任何场景求导数,相当于matlab自带的求导模块
效果图如下
代码如下,设置2个离散状态(即sizes.NumDiscStates = 2; %离散状态),用于保存上一时刻的状态量u(n-1)和u时间量t(n-1),则更新离散状态量时,sys向量的长度要为2,不然编译时会报错。这里的x(2)相当于u(n-1),这里的x(3)相当于t(n-1)。
输出du = [u - u(n - 1)]/[ t - t(n - 1)],即为输入u的导数
function [sys,x0,str,ts]=third(t,x,u,flag)
switch flag,
case 0,
[sys,x0,str,ts]=mdlInitializeSizes;
case 1,
sys=mdlDerivatives(t,x,u);
case 2,
sys=mdlUpdate(t,x,u);
case 3,
sys=mdlOutputs(t,x,u);
case { 4, 9 }
sys = [];
otherwise
end
function [sys,x0,str,ts]=mdlInitializeSizes
sizes = simsizes;
sizes.NumContStates =1; %连续状态
sizes.NumDiscStates = 2; %离散状态
sizes.NumOutputs = 2;
sizes.NumInputs = 1;
sizes.DirFeedthrough = 1;
sizes.NumSampleTimes = 0;
sys=simsizes(sizes);
x0=[0,0,0]; % x(1)积分 x(2)微分 x(3)时间t
str=[];
ts=[];
function sys=mdlDerivatives(t,x,u) %实现对输入的积分
x(1) = u;
sys=x(1);
function sys=mdlUpdate(t,x,u) %实现对输入的求导
x(2)=u;
x(3)=t;
sys=[x(2),x(3)];
function sys=mdlOutputs(t,x,u)
if (t-x(3))>0 %避免在最初的一个采样点,分母为零,导致输出结果异常的大
du=(u-x(2))/(t-x(3));
else
du=0;
end
sys = [du,u];
将sizes.NumOutputs = 2改为sizes.NumOutputs = 3,即输出向量维度为3
再将function sys=mdlOutputs(t,x,u)处的sys = [ du,u ]改为sys = [ du,u,x(1) ],即将输入的积分函数输出,同时保证输出向量维度与上文的sizes.NumOutputs = 3对应。
同时输出导数,积分函数的图像如下,如果导数在0处出现突变,则改变求解器步长为定步长1e-4