streamlice函数的可能错误或只是在MATLAB中滥用它?

时间:2013-12-30 20:15:44

标签: matlab plot

问题很简单,非常简单:我想用these equations计算条形磁铁(等于螺线管磁场)的磁流量。我的MATLAB版本是R2013a

执行作业的函数magnetic_field(它返回一个带坐标(r,z)和字段(Br,Bz)的结构, B (r,z) = Br(r,z) r + Bz(r,z) z 被计算出来),在这个问题的最后。

然后我打电话给

>> t = magnetic_field(2e-2, 16e-2, 20, -6e-2, 6e-2, 0.5e-2, -18.2e-2, 18.2e-2, 1e-2);
>> streamslice(t.r, t.z, t.Br, t.Bz)

请注意,t.rt.z是一个meshgrid结果,其中计算了BrBz(请参阅for循环函数magnetic_field)。因此,所有这四个矩阵都具有相同的size

MATLAB给出错误:

  

尝试访问startgrid(NaN,13);指数必须是正面的   整数或逻辑。

     

溪流中的错误> nicestreams(第324行)                       startgrid(RR,CC)= 1;

     

溪流中的错误(第134行)           [vertsout,avertsout] = nicestreams(x,y,u,v,密度,箭头);

奇怪之处在于:如果我更改了网格,则streamlice不会出错:

>> t = magnetic_field(2e-2, 16e-2, 20, -2, 2, 0.1, -2, 2, 0.1);

虽然它会产生一个非常奇怪的结果(因为解决方案只定义为正r,我猜是假的)。

我去检查了MATLAB样本数据,比如wind数据:

>> w = load('wind');
>> streamslice(w.x(:,:,5), w.y(:,:,5), w.u(:,:,5), w.v(:,:,5))

正确绘图。但是,如果我从5更改为23101215,则MATLAB会显示非常类似的错误我的那个:

  

尝试访问startgrid(2,0); index必须是正整数或逻辑。

     

溪流中的错误> nicestreams(第324行)                      startgrid(RR,CC)= 1;

     

溪流中的错误(第134行)          [vertsout,avertsout] = nicestreams(x,y,u,v,密度,箭头);

不同之处在于,对于示例数据,错误是streamslice尝试访问0索引,而在我的情况下,它尝试访问NaN索引。< / p>

因此,我坚持两种可能性:

1)我的数据(即变量BrBz)没有streamslice函数所需的结构 2)这是streamslice函数

中的错误

您怎么看?

有什么建议吗?

function res = magnetic_field(a, L, I, rMin, rMax, dr, zMin, zMax, dz)    
    Nr = (rMax - rMin) ./ dr + 1;
    Nz = (zMax - zMin) ./ dz + 1;

    % calculating dependent constants
    mu0div2pi = 2e-7;
    Lm1 = 1 / L; % in 1/m
    Ldiv2 = L / 2;
    constZ = Lm1 .* I * mu0div2pi / 4;
    constR = Lm1 .* I * mu0div2pi;

    % defining functions
    kSqr = @(ar4, ar2, zeta) ar4 ./ (ar2 + zeta .^ 2);
    hSqr = @(ar4, ar2) ar4 ./ ar2;
    zetaPlus = @(z, Ldiv2) z + Ldiv2;
    zetaMinus = @(z, Ldiv2) z - Ldiv2;
    IntBr = @(kSqr, eK) ((kSqr - 2) .* eK + 2 .* ellipticE(kSqr)) ./ sqrt(kSqr);
    IntBz = @(kSqr, hSqr, r, zeta, a, eK) zeta .* sqrt(kSqr) .* (eK + ellipticPi(hSqr, kSqr) .* (a - r) ./ (a + r));

    % creating grid
    [r, z] = meshgrid(linspace(rMin, rMax, Nr), linspace(zMin, zMax, Nz));
    [m, n] = size(r);
    NN = m * n;

    Br = zeros(m,n);
    Bz = zeros(m,n);
    for i = 1:NN
        ar4 = 4 .* a .* r(i);
        ar2 = (a + r(i)) .^ 2;
        hh = hSqr(ar4, ar2);
        zP = zetaPlus(z(i), Ldiv2);
        zM = zetaMinus(z(i), Ldiv2);
        kkPlus = kSqr(ar4, ar2, zP);
        kkMinus = kSqr(ar4, ar2, zM);
        eKPlus = ellipticK(kkPlus);
        eKMinus = ellipticK(kkMinus);
        Br(i) = constR .* sqrt(a ./ r(i)) .* (IntBr(kkPlus, eKPlus) - IntBr(kkMinus, eKMinus));
        Bz(i) = constZ .* ( IntBz(kkPlus, hh, r(i), zP, a, eKPlus) - IntBz(kkMinus, hh, r(i), zM, a, eKMinus) ) ./ sqrt(a .* r(i));
    end
    res.a = a;
    res.L = L;
    res.I = I;
    res.r = r;
    res.z = z;
    res.Br = Br;
    res.Bz = Bz;
end

2 个答案:

答案 0 :(得分:1)

使用wind数据集的错误显然是streamlice中的一个错误,由错误处理的舍入错误引起。它出现在R2013b中。我建议你把它报告给TheMathWorks。

使用您的magnetic_field数据集的错误似乎也是streamlice中的错误。我在R2013a中得到了同样的错误。但是,R2013b没有错误(并且输出看起来很合理),所以看起来该版本中的bug已被修复。

答案 1 :(得分:1)

这似乎是streamslice中提到的@ user664303中的错误,您应该报告它。


w = load('wind');
i = 2;
streamslice(w.x(:,:,i), w.y(:,:,i), w.u(:,:,i), w.v(:,:,i))

按照指示使用wind数据集(我正在使用MATLAB R2013b),错误似乎是由舍入错误引起的;值xc-xmin意外地返回一个接近机器精度的非常小的负数,反过来通过调用-1函数变为floor。此结果(递增1)稍后用于索引,从而导致错误。

好消息是,我相信这里有一个简单的解决方案;通过拨打floor来取代对fix的通话(不要双关语)。这应该执行向零舍入而不是向负无穷大舍入,在正数的情况下(在此上下文中似乎是预期的)是等效的,一直等于捕捉到轻微的舍入错误,这可能导致一个非常小的负数,而不应该发生一个零,并纠正它。

我必须在streamslice.m文件中的六个不同位置执行此更改(只需将所有floor替换为fix)。以下是更改的补丁文件:

--- old/streamslice.m
+++ new/streamslice.m
@@ -321,8 +321,8 @@
                     yc = vv(j,2);
-                    cc = floor( (xc-xmin)*ixrangecs )+1;
-                    rr = floor( (yc-ymin)*iyrangers )+1;
+                    cc = fix( (xc-xmin)*ixrangecs )+1;
+                    rr = fix( (yc-ymin)*iyrangers )+1;
                     startgrid(rr,cc)=1;

-                    cc = floor( (xc-xmin)*ixrangece )+1;
-                    rr = floor( (yc-ymin)*iyrangere )+1;
+                    cc = fix( (xc-xmin)*ixrangece )+1;
+                    rr = fix( (yc-ymin)*iyrangere )+1;
                     if endgrid(rr,cc)==1
@@ -336,4 +336,4 @@
                     if arrows
-                        cc = floor( (xc-xmin)*ixrangeca )+1;
-                        rr = floor( (yc-ymin)*iyrangera )+1;
+                        cc = fix( (xc-xmin)*ixrangeca )+1;
+                        rr = fix( (yc-ymin)*iyrangera )+1;
                         if j>1 && arrowgrid(rr,cc)==0

比较R2013a和R2013b之间的功能,文件是相同的。所以我认为这个解决方法也适用于该版本。请尝试实际数据,看看它是否有效..


编辑:

正如您所发现的,streamslice函数中似乎存在第二个错误。它仅在数据包含NaN值时影响代码。据我所知,这是解决方法:

--- old/streamslice.m
+++ new/streamslice.m
@@ -302,7 +302,7 @@
             for q = 1:2
                 vv = verts{q};

-                nanpos = find(isnan(vv));
+                nanpos = find(any(isnan(vv),2));
                 if ~isempty(nanpos)
                     if nanpos(1)==1
                         vv = [];

值得注意的是,使用您的函数生成数据:

t = magnetic_field(2e-2, 16e-2, 20, -6e-2, 6e-2, 0.5e-2, -18.2e-2, 18.2e-2, 1e-2);

在R2013a和R2013b之间给出不同的结果(特别是使用R2013a,t.Bz有一列所有NaN / Inf值都没有出现在R2013b生成的数据中)...这就解释了为什么Nan-bug没有' t出现在R2013b中。