如何在matplotlib.pyplot.streamplot中避免螺旋流线?

gfttwv5a  于 2023-11-22  发布在  其他
关注(0)|答案(2)|浏览(178)

我试图使用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)

nzrxty8p

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,这不适用于任何场,但适用于平面磁场。对于上述示例(进行了一些调整):

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 = -5+10*(np.arange(201)+0.5)/201
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],

# Build the stream function and plot its isolines
dx, dy = x[0,1]-x[0,0], y[1,0]-y[0,0]
psi = np.cumsum(u,axis=0)*dy-np.cumsum(v[0:1,:],axis=1)*dx
psi -= np.min(psi)
levels = np.linspace(psi[101,81], psi[101,119], 31)
plt.contour(x, y, psi, levels=levels, colors='blue', linewidths=1.0)

# 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()

字符串
x1c 0d1x的数据

c8ib6hqw

c8ib6hqw2#

在查看了streamplot源代码之后,我得到了为什么流线通过某种“隧道效应”穿过掩蔽区域的解释:积分过程以步长从一个位置跳到另一个位置,该步长可能恰好大于掩蔽区域的宽度。步长的尺度不能作为streamplot()的参数直接访问,但可以通过density参数间接控制(这有点奇怪,因为当streamplot与起始点一起使用时,该参数不应该有任何影响)。只需将density=60添加到上面代码中的流图参数即可修复它:

这也是为了解决流线没有延伸到掩蔽区域的边界的事实。通过增加密度参数的值来减小步长是可能增加流线的精确度,尽管以增加计算时间为代价。
这仍然是一个解决方法,但是为了得到完整的和封闭的流线,我必须使用两个掩码,并对使用它们获得的流线进行重新排序,这不是很方便,并且为此调整掩码的大小和位置有点麻烦。不幸的是,在代码的当前状态下,似乎没有简单的方法直接做到这一点。

相关问题