13

私は、matplotlib を使用して球の周りの磁場の流線をプロットしようとしていますが、うまく機能します。ただし、結果の画像は対称ではありませんが、対称である必要があります(と思います)。 ここに画像の説明を入力

これは、画像を生成するために使用されるコードです。長々と失礼しましたが、機能しないスニペットを投稿するよりはましだと思いました。また、あまりPythonicではありません。これは、Matlab から変換したためで、予想よりも簡単でした。

from __future__ import division
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Circle

def cart2spherical(x, y, z):
    r = np.sqrt(x**2 + y**2 + z**2)
    phi = np.arctan2(y, x)
    theta = np.arccos(z/r)
    if r == 0:
        theta = 0
    return (r, theta, phi)

def S(theta, phi):
    S = np.array([[np.sin(theta)*np.cos(phi), np.cos(theta)*np.cos(phi), -np.sin(phi)],
                  [np.sin(theta)*np.sin(phi), np.cos(theta)*np.sin(phi),  np.cos(phi)],
                  [np.cos(theta),             -np.sin(theta),             0]])
    return S

def computeB(r, theta, phi, a=1, muR=100, B0=1):
    delta = (muR - 1)/(muR + 2)
    if r > a:
        Bspherical = B0*np.array([np.cos(theta) * (1 + 2*delta*a**3 / r**3),
                                  np.sin(theta) * (delta*a**3 / r**3 - 1),
                                  0])
        B = np.dot(S(theta, phi), Bspherical)
    else:
        B = 3*B0*(muR / (muR + 2)) * np.array([0, 0, 1])
    return B

Z, X = np.mgrid[-2.5:2.5:1000j, -2.5:2.5:1000j]
Bx = np.zeros(np.shape(X))
Bz = np.zeros(np.shape(X))
Babs = np.zeros(np.shape(X))
for i in range(len(X)):
    for j in range(len(Z)):
        r, theta, phi = cart2spherical(X[0, i], 0, Z[j, 0])
        B = computeB(r, theta, phi)
        Bx[i, j], Bz[i, j] = B[0], B[2]
        Babs[i, j] = np.sqrt(B[0]**2 + B[1]**2 + B[2]**2)

fig=plt.figure()
ax=fig.add_subplot(111)

plt.streamplot(X, Z, Bx, Bz, color='k', linewidth=0.8*Babs, density=1.3,
               minlength=0.9, arrowstyle='-')
ax.add_patch(Circle((0, 0), radius=1, facecolor='none', linewidth=2))
plt.axis('equal')
plt.axis('off')
fig.savefig('streamlines.pdf', transparent=True, bbox_inches='tight', pad_inches=0)
4

4 に答える 4

8

まず、好奇心のために、なぜ対称データをプロットしたいのでしょうか? の半分をプロットしても問題ないのはなぜですか?

つまり、これはハッキングの可能性があります。Hooked が提案したようにマスク配列を使用して、その半分をプロットできます。

mask = X>0
BX_OUT = Bx.copy()
BZ_OUT = Bz.copy()
BX_OUT[mask] = None
BZ_OUT[mask] = None
res = plt.streamplot(X, Z, BX_OUT, BZ_OUT, color='k', 
           arrowstyle='-',linewidth=1,density=2)

次に、streamplot の結果を res に保存し、線を抽出して、反対の X 座標でプロットします。

lines = res.lines.get_paths()
for l in lines:
    plot(-l.vertices.T[0],l.vertices.T[1],'k')

このハックを使用して、2D プロットから流線と矢印を抽出し、3D 変換を適用して mplot3d でプロットしました。写真は私の質問の 1 つです

于 2013-05-04T10:05:05.423 に答える
6

マスクを使用して、関心のある 2 つの領域を分離します。

mask = np.sqrt(X**2+Z**2)<1

BX_OUT = Bx.copy()
BZ_OUT = Bz.copy()
BX_OUT[mask] = None
BZ_OUT[mask] = None
plt.streamplot(X, Z, BX_OUT, BZ_OUT, color='k', 
               arrowstyle='-', density=2)

BX_IN = Bx.copy()
BZ_IN = Bz.copy()
BX_IN[~mask] = None
BZ_IN[~mask] = None
plt.streamplot(X, Z, BX_IN, BZ_IN, color='r', 
               arrowstyle='-', density=2)

ここに画像の説明を入力

結果のプロットは完全に対称ではありません、アルゴリズムにヒントを与えることで、以前のものよりもはるかに近くなっています。グリッド ビアの密度とmeshgridパラメーターdensityを調整して、探している効果を実現します。

于 2013-05-02T20:47:15.887 に答える
2

代わりに物理学を使用してください... 磁場は z (垂直) 軸に対して対称です! streamplotしたがって、2つの 'sが必要です。

plt.streamplot(X, Z, Bx, Bz, color='k', linewidth=0.8*Babs, density=1.3, minlength=0.9, arrowstyle='-')
plt.streamplot(-X, Z, -Bx, Bz, color='k', linewidth=0.8*Babs, density=1.3, minlength=0.9, arrowstyle='-')
于 2014-01-14T00:02:54.173 に答える