MATLAB根函数在MATLAB和Simulink中的不同行为?

MATLAB根函数在MATLAB和Simulink中的不同行为?,matlab,simulink,matlab-coder,Matlab,Simulink,Matlab Coder,我在MATLAB中实现了以下用户定义的函数: function Q = Calc_Q(Head, freq) b6 = [3.7572E-07 -1.5707E-05 6.0490E-03 5.0018E-02 2.1180E-01]; b5 = [-9.0927E-06 8.9033E-04 -3.2415E-02 5.4525E-01 -8.1649E+00] / 10e2; b4 = [7.5172E-06 -5.6565E-04 1.0024E-02 3.5888E-01 3.8894E

我在MATLAB中实现了以下用户定义的函数:

function Q = Calc_Q(Head, freq)
b6 = [3.7572E-07 -1.5707E-05 6.0490E-03 5.0018E-02 2.1180E-01];
b5 = [-9.0927E-06 8.9033E-04 -3.2415E-02 5.4525E-01 -8.1649E+00] / 10e2;
b4 = [7.5172E-06 -5.6565E-04 1.0024E-02 3.5888E-01 3.8894E-02] / 10e5;
b3 = [-4.8767E-06 4.8787E-04 -1.3311E-02 -1.2189E-01 -5.3522E+00] / 10e8;
b2 = [5.9227E-06 -8.1716E-04 3.5392E-02 -4.5413E-01 1.9547E+00] / 10e11;
b1 = [-2.0004E-06 2.9027E-04 -1.3754E-02 2.3490E-01 -1.2363E+00] / 10e14;

a = [polyval(b1,abs(freq)), polyval(b2, abs(freq)), polyval(b3, abs(freq)), polyval(b4, abs(freq)), polyval(b5, abs(freq)), polyval(b6, abs(freq)) - Head];

Q_roots = roots(a);
%Delete roots with imaginary part
i = 1;
while i <= length(Q_roots)
    if(imag(Q_roots(i)) ~= 0)
        Q_roots(i) = [];
        i = i - 1;
    end
    i = i + 1;
end
%Delete roots with real part greater then 3100
i = 1;
while i <= length(Q_roots)
    if(Q_roots(i) >= 3100 || Q_roots(i) < 0)
        Q_roots(i) = [];
        i = i - 1;
    end
    i = i +1;
end

if freq < 0
    Q = real(Q_roots(1)) * -1;
else
    Q = real(Q_roots(1));        
end
end

有什么想法吗

我发现了问题

来自不同论坛:

嗨,科斯敏

我看了一下嵌入式MATLAB的根的实现 函数块(\toolbox\eml\lib\matlab\polyfun\root.m)。 上面写着:

%限制:%s输出大小始终可变。%输出为 总是很复杂根的顺序可能与MATLAB不同。% 条件较差的多项式的根可能与MATLAB不匹配。最后 句子让你头疼(是的,你的多项式是 条件差!)。如果你看一下情节,你会发现 曲线几乎不接触x轴

不过我有一个建议:值-z/b是一个(非常)好的值 要查找的根的近似值

提图斯

显然,simulink中的根函数并不总能找到给定多项式的所有根。 这是不幸的,不容易解决。但我确实找到了解决办法

对于我要解的所有不同多项式,我知道我感兴趣的根的区间([-3000,3000])

我基本上只需要从-3000到3000执行50步,直到函数降到0以下。然后我知道根的近似解。我使用这个近似作为牛顿-拉斐逊方法的种子

用给定的种子直接实现牛顿-拉斐逊方法来求解我必须求解的所有多项式是行不通的,因为有时它会迭代到不同的根(我不感兴趣的根)

代码如下:

function Q = Calc_Q(Head, freq)
    b6 = [3.7572E-07 -1.5707E-05 6.0490E-03 5.0018E-02 2.1180E-01];
    b5 = [-9.0927E-06 8.9033E-04 -3.2415E-02 5.4525E-01 -8.1649E+00] / 10e2;
    b4 = [7.5172E-06 -5.6565E-04 1.0024E-02 3.5888E-01 3.8894E-02] / 10e5;
    b3 = [-4.8767E-06 4.8787E-04 -1.3311E-02 -1.2189E-01 -5.3522E+00] / 10e8;
    b2 = [5.9227E-06 -8.1716E-04 3.5392E-02 -4.5413E-01 1.9547E+00] / 10e11;
    b1 = [-2.0004E-06 2.9027E-04 -1.3754E-02 2.3490E-01 -1.2363E+00] / 10e14;

    %coeff for the polynominal
    a = [polyval(b1,abs(freq)), polyval(b2, abs(freq)), polyval(b3, abs(freq)), polyval(b4, abs(freq)), polyval(b5, abs(freq)), polyval(b6, abs(freq)) - Head];

    %coeff for the derrivative of polynominal
    da = [5*a(1) 4*a(2) 3*a(3) 2*a(4) a(5)];

    Q = -3000;
    %Search for point where function goes below 0
    while (polyval(a, Q) > 0)
        Q = Q + 25;
    end    
    error_max = 0.01
    iter_counter = 1;
    while abs(polyval(a,Q)) >= error_max && iter_counter <= 1000
        Q = Q - polyval(a, Q)/polyval(da, Q);
        iter_counter = iter_counter + 1;
        error = abs(polyval(a,Q));
    end
    if(freq < 0)
        Q = Q * - 1;
    end
end
函数Q=Calc_Q(水头、频率)
b6=[3.7572E-07-1.5707E-05 6.0490E-03 5.0018E-02 2.1180E-01];
b5=[-9.0927E-06 8.9033E-04-3.2415E-02 5.4525E-01-8.1649E+00]/10e2;
b4=[7.5172E-06-5.6565E-04 1.0024E-02 3.5888E-01 3.8894E-02]/10e5;
b3=[-4.8767E-06 4.8787E-04-1.3311E-02-1.2189E-01-5.3522E+00]/10e8;
b2=[5.9227E-06-8.1716E-04 3.5392E-02-4.5413E-01 1.9547E+00]/10e11;
b1=[-2.0004E-06 2.9027E-04-1.3754E-02 2.3490E-01-1.2363E+00]/10e14;
%多项式系数
a=[polyval(b1,abs(频率)),polyval(b2,abs(频率)),polyval(b3,abs(频率)),polyval(b4,abs(频率)),polyval(b5,abs(频率)),polyval(b6,abs(频率))-头部];
%多项式的竞争系数
da=[5*a(1)4*a(2)3*a(3)2*a(4)a(5)];
Q=-3000;
%搜索函数低于0的点
while(polyval(a,Q)>0)
Q=Q+25;
结束
误差_max=0.01
iter_计数器=1;

当abs(polyval(a,Q))>=error\u max&&iter\u counter时,问题很可能是由于您的逻辑消除了虚部中不完全为零的任何根。这是一种数学思维方式,在数值上并不有效,至少在一般情况下不有效。在这两种情况下都可能找到所有的根(没有其他限制),但在Simulink和代码生成中,问题被视为一个复杂的问题,一些根可能带着微小的虚部返回。如果根的虚部不完全为零,则不删除根,而是使用数值上不重要的虚部(相对于实部非常小或全部非常小)消除根。差不多

tol = 10*eps(class(Q_roots));
keepers = abs(imag(Q_roots)) < tol*max(abs(real(Q_roots)),1) & ...
    real(Q_roots) >= 0 & real(Q_roots) <= 3100;
Q_roots = Q_roots(keepers);
tol=10*eps(类(Q_根));
keepers=abs(imag(Q_根))实(Q_根)>=0&实(Q_根)=0&&r您使用哪个Simulink块调用此函数?Simulink中函数的输入是否正常?我使用了“MATLAB函数”块。。。我猜输入是可以的。。。我刚刚将两个常量连接到inputsMichael,如果我查看函数root()在Matlab和simulink中分别产生的根,simulink确实会产生不同的结果(即找到的根较少,而不是我感兴趣的根)。你能提供给我确切的Head和Freq输入来演示这一点吗?我们希望在数字上有细微的差异和不同的顺序。我们不期望“更少的根”或“不同的根”,除非在极端病态的情况下,在这种情况下,一个或另一个可能会给出更令人满意的结果,但并不一致。MATLAB在这方面的主要优势是能够对实矩阵使用特征值解算器,这将为非实根生成精确的复共轭对。
tol = 10*eps(class(Q_roots));
keepers = abs(imag(Q_roots)) < tol*max(abs(real(Q_roots)),1) & ...
    real(Q_roots) >= 0 & real(Q_roots) <= 3100;
Q_roots = Q_roots(keepers);
Q = nan('like',a);
tol = 10*eps(class(a));
for k = 1:numel(Q_roots)
    r = real(Q_roots(k));
    if abs(imag(Q_roots(k))) < tol*max(abs(r),1) && r >= 0 && r <= 3100;
        Q = r;
        break
    end
end

if freq < 0
    Q = -Q;
end