Matplotlib - 投影极坐标中的等值线图和箭袋图

Matplotlib - contour and quiver plot in projected polar coordinates

我需要绘制在 (r,theta) 坐标中不均匀网格上定义的标量场和矢量场的等值线图和箭袋图。

作为我遇到的问题的一个最小例子,考虑磁偶极子的 Stream function 等高线图,这种函数的等高线是相应的矢量场(在本例中为磁场)。

下面的代码采用 (r,theta) 坐标中的不均匀网格,将其映射到笛卡尔平面并绘制流函数的等高线图。

import numpy as np
import matplotlib.pyplot as plt

r = np.logspace(0,1,200)
theta = np.linspace(0,np.pi/2,100)

N_r = len(r)
N_theta = len(theta)

# Polar to cartesian coordinates
theta_matrix, r_matrix = np.meshgrid(theta, r)
x = r_matrix * np.cos(theta_matrix)
y = r_matrix * np.sin(theta_matrix)

m = 5
psi = np.zeros((N_r, N_theta))

# Stream function for a magnetic dipole
psi = m * np.sin(theta_matrix)**2 / r_matrix

contour_levels = m * np.sin(np.linspace(0, np.pi/2,40))**2.

fig, ax = plt.subplots()
# ax.plot(x,y,'b.')  # plot grid points
ax.set_aspect('equal')
ax.contour(x, y, psi, 100, colors='black',levels=contour_levels)
plt.show()

虽然出于某种原因,我得到的情节看起来并不正确:

如果我在轮廓函数调用中交换 x 和 y,我会得到想要的结果:

当我尝试绘制定义在同一网格上并映射到 x-y 平面的 向量场 的箭袋图时,同样的事情发生了,除了交换 x并且函数调用中的 y 不再起作用。

好像我在某个地方犯了一个愚蠢的错误,但我不知道是什么。

如果psi = m * np.sin(theta_matrix)**2 / r_matrix 然后 psi 随着 theta 从 0 到 pi/2 增加而 psi 随着 r 增加而减少。

因此,随着 theta 的增加,psi 的等高线应该在 r 中增加。那结果 在一条从中心向外辐射的逆时针曲线中。这是 与您发布的第一个情节一致,并且您的代码的第一个版本返回的结果带有

ax.contour(x, y, psi, 100, colors='black',levels=contour_levels)

确认结果合理性的另一种方法是查看 psi:

的曲面图
import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d.axes3d as axes3d

r = np.logspace(0,1,200)
theta = np.linspace(0,np.pi/2,100)

N_r = len(r)
N_theta = len(theta)

# Polar to cartesian coordinates
theta_matrix, r_matrix = np.meshgrid(theta, r)
x = r_matrix * np.cos(theta_matrix)
y = r_matrix * np.sin(theta_matrix)

m = 5

# Stream function for a magnetic dipole
psi = m * np.sin(theta_matrix)**2 / r_matrix

contour_levels = m * np.sin(np.linspace(0, np.pi/2,40))**2.

fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, projection='3d')
ax.set_aspect('equal')

ax.plot_surface(x, y, psi, rstride=8, cstride=8, alpha=0.3)
ax.contour(x, y, psi, colors='black',levels=contour_levels)
plt.show()