我试图使用matplotlib.pyplot.streamplot
来显示使用magpylib生成的磁场。我从他们的一个例子中改编了下面的内容,以显示具有受控间距的完整线条,但我有一些问题,即一些理论上闭合的磁力线实际上并不闭合,而是螺旋形的,可能是由于数值不稳定或近似,来自matplotlib,从magpylib
或从两者。有没有一种方法可以防止不间断的流线螺旋,或者更好的是,告诉matplotlib在可能的情况下关闭流线本身?
代码:
import matplotlib.pyplot as plt
import numpy as np
import magpylib as magpy
# Create a Matplotlib figure
fig, ax = plt.subplots(figsize=(10, 10))
# Create an observer grid in the xz-symmetry plane
ts = np.linspace(-5,5,200)
grid = np.array([[(x,0,z) for x in ts] for z in ts]) # slow Python loop
# Compute the B-field of a cube magnet on the grid
cube = magpy.magnet.Cuboid(magnetization=(0, 0, -1000), dimension=(2, 2, 2))
B = cube.getB(grid)
x, y, u, v = grid[:,:,0], grid[:,:,2], B[:, :, 0], B[:, :, 2],
# Mask for breaking the streamlines
u[98:102, 80:120] = np.nan
v[98:102, 80:120] = np.nan
top_seed_points = np.array([np.linspace(-1.0, +1.0, 21), np.ones(21)])[:,:-3]
bottom_seed_points = np.array([np.linspace(-1.0, +1.0, 21), -np.ones(21)])[:,3:]
left_seed_points = np.array([-np.ones(4), 1-(0.05+(np.linspace(0, 1, 4, endpoint=False))**2)])[:,:3]
right_seed_points = np.array([np.ones(4), (0.05+(np.linspace(0, 1, 4, endpoint=False))**2-1)])[:,:3]
seed_points = np.concatenate((top_seed_points, bottom_seed_points, left_seed_points, right_seed_points[:, :3]), axis=1)
# Display the B-field with streamplot using log10-scaled
# color function and linewidth
splt = ax.streamplot(
x, y, u, v,
start_points=seed_points.T,
broken_streamlines=False,
)
ticks = np.array([3,10,30,100,300])
# Outline magnet boundary
ax.plot([1, 1, -1, -1, 1], [1, -1, -1, 1, 1], "k-", lw=2)
ax.set_xlim([-5, 5])
ax.set_ylim([-5, 5])
# Figure styling
ax.set(
xlabel="x-position (mm)",
ylabel="z-position (mm)",
)
plt.tight_layout()
plt.show()
字符串
结果:
我试图打破螺旋使用面具,但一些流线设法使它通过面具地区(我会认为是一个错误)和螺旋无论如何。
注意:如果我以这种方式进行掩蔽,结果是相同的:
# Mask for breaking the streamlines
mask = np.zeros(u.shape, dtype=bool)
mask[98:102, 80:120] = True
u = np.ma.array(u, mask=mask)
v = np.ma.array(v, mask=mask)
型
2条答案
按热度按时间nzrxty8p1#
最后,with the help of Jody Klymak, Member of Matplotlib Developers,我发现了一个替代的解决方案,用于显示流线,而不使用流图。这个想法是build a stream function from the vector field,并绘制其轮廓。流函数psi是通过整合从固定点开始的任何路径构建的:
psi(x,y)= u.dy - v.dx的积分(在C上从原点到(x,y))
即,dpsi/dx = -v和dpsi/dy = u。如果div(u,v)= 0,则结果不依赖于C,这不适用于任何场,但适用于平面磁场。对于上述示例(进行了一些调整):
字符串
x1c 0d1x的数据
c8ib6hqw2#
在查看了
streamplot
源代码之后,我得到了为什么流线通过某种“隧道效应”穿过掩蔽区域的解释:积分过程以步长从一个位置跳到另一个位置,该步长可能恰好大于掩蔽区域的宽度。步长的尺度不能作为streamplot()
的参数直接访问,但可以通过density
参数间接控制(这有点奇怪,因为当streamplot
与起始点一起使用时,该参数不应该有任何影响)。只需将density=60
添加到上面代码中的流图参数即可修复它:这也是为了解决流线没有延伸到掩蔽区域的边界的事实。通过增加密度参数的值来减小步长是可能增加流线的精确度,尽管以增加计算时间为代价。
这仍然是一个解决方法,但是为了得到完整的和封闭的流线,我必须使用两个掩码,并对使用它们获得的流线进行重新排序,这不是很方便,并且为此调整掩码的大小和位置有点麻烦。不幸的是,在代码的当前状态下,似乎没有简单的方法直接做到这一点。