在 Simulink 中求解子系统内的 ODE

Solving ODEs inside a Subsystem in Simulink

我正在尝试弄清楚如何求解 Simulink 模型中子系统内的 ODE 系统。基本上,每次调用此子系统(在模拟时钟的每个滴答声(固定步长)时发生)都需要求解 ODE。所以子系统有一个不同的 "clock"。

我有一个 M 文件实现了 ODE 系统的功能。目前,我有一个 MATLAB Function 块。它需要很多我可以从基础工作区获得的参数(通过 evalin 并在开始时使用 coder.extrinsic('evalin'))。但是我不允许定义 function_handle 对象或内部函数来参数化 ode* 使用的函数。我认为,如果我能够解决这个模块中的 ODE,我就会解决我的问题。不过那些限制都是"ruining"而已。

如果您对如何完成此操作有任何想法,我将不胜感激。我欢迎不同的方法。

谢谢。

编辑

下面给出一个简单的例子。它试图通过随机更改 mu 参数来求解 van der Pol 方程。这是我目前的主要想法,由于上面提到的问题,这个想法行不通。

这是带有子系统的主模型:

这是子系统:

这是 MATLAB Function 模块实现(注意 @ 符号中有错误,因为不允许定义 function_handle 对象):

只需使用 MATLAB Function 块作为包装器。将大部分代码放入 "standard" MATLAB 函数(即一个可从 MATLAB 调用的函数,而不是 MATLAB 函数块)并从 MATLAB 函数块调用该函数(在将其定义为 coder.extrinsic 之后)。

这会比 复杂一点。优点是它允许您在必要时生成独立代码,而外部函数与独立代码生成不兼容。

自 MATLAB R2014b 起,代码生成支持函数 ode23ode45,因此如果您的 MATLAB 版本至少是新版本,则这适用。假设是这样,您看到的主要限制是代码生成不支持匿名函数。

用持久变量模拟匿名函数参数

但是,这些参数化的匿名函数可以使用具有持久性的普通函数来模拟。要使用参数 mu 模拟您的函数,请创建一个 MATLAB 文件 odefcn.m:

function x = odefcn(t,y)
%#codegen
persistent mu;
if isempty(mu)
  % Adjust based on actual size, type and complexity
  mu = 0;
end
if ischar(t) && strcmp(t,'set')
  % Syntax to set parameter
  mu = y;
else
  x = [y(2); mu*(1-y(1)^2)*y(2)-y(1)];
end

然后在 MATLAB 函数块中,使用:

function y = fcn(mu)
%#codegen
% Set parameter
odefcn('set',mu);

% Solve ODE
[~,Y] = ode45(@odefcn,[0, 20], [2; 0]);
y = Y(end,1);

这应该适用于模拟和代码生成。如果您需要更多参数,您可以向 odefcn 添加更多参数。