问题很简单,非常简单:我想用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.r
和t.z
是一个meshgrid
结果,其中计算了Br
和Bz
(请参阅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
更改为2
,3
,10
,12
或15
,则MATLAB会显示非常类似的错误我的那个:
尝试访问startgrid(2,0); index必须是正整数或逻辑。
溪流中的错误> nicestreams(第324行) startgrid(RR,CC)= 1;
溪流中的错误(第134行) [vertsout,avertsout] = nicestreams(x,y,u,v,密度,箭头);
不同之处在于,对于示例数据,错误是streamslice
尝试访问0
索引,而在我的情况下,它尝试访问NaN
索引。< / p>
因此,我坚持两种可能性:
1)我的数据(即变量Br
和Bz
)没有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
答案 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中。