首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >计算和绘制向量场

计算和绘制向量场
EN

Stack Overflow用户
提问于 2014-08-17 01:18:43
回答 1查看 22K关注 0票数 16

我正在尝试使用以下公式为给定的对象绘制一个势场:

代码语言:javascript
复制
U=-α_goal*e^(-((x-x_goal )^2/a_goal +(y-y_goal^2)/b_goal ) )

使用以下代码

代码语言:javascript
复制
    # Set limits and number of points in grid
    xmax = 10.0
    xmin = -xmax
    NX = 20
    ymax = 10.0
    ymin = -ymax
    NY = 20
    # Make grid and calculate vector components
    x = linspace(xmin, xmax, NX)
    y = linspace(ymin, ymax, NY)
    X, Y = meshgrid(x, y)
    x_obstacle = 0
    y_obstacle = 0
    alpha_obstacle = 1
    a_obstacle = 1
    b_obstacle = 1
    P = -alpha_obstacle * exp(-(X - x_obstacle)**2 / a_obstacle + (Y - y_obstacle)**2 / b_obstacle)
    Ey,Ex = gradient(P)
    print Ey
    print Ex

    QP = quiver(X, Y, Ex, Ey)

    show()

这段代码计算了一个势场。我怎样才能很好地绘制这个势场呢?另外,给定一个势场,将其转换为向量场的最佳方法是什么?(矢量场是势场的负梯度。)

如果有任何帮助,我将不胜感激。

我尝试过使用np.gradient(),但结果并不是我所期望的:

我所期望的,是这样的东西:

编辑:更改代码中的两行后:

代码语言:javascript
复制
y, x = np.mgrid[500:-100:200j, 1000:-100:200j] 
p = -1 * np.exp(-((x - 893.6)**2 / 1000 + (y - 417.35)**2 / 1000))

我有一个错误的图:它似乎是左右颠倒的(箭头似乎在正确的位置,但不是在领域中):

编辑:通过更改为y, x = np.mgrid[500:-100:200j, -100:1000:200j]进行了修复。您知道为什么吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-08-17 03:24:53

首先,让我们在一个规则的网格上评估它,类似于您的示例代码。(顺便说一句,计算公式的代码中有一个错误。它在exp中缺少负值。):

代码语言:javascript
复制
import numpy as np
import matplotlib.pyplot as plt

# Set limits and number of points in grid
y, x = np.mgrid[10:-10:100j, 10:-10:100j]

x_obstacle, y_obstacle = 0.0, 0.0
alpha_obstacle, a_obstacle, b_obstacle = 1.0, 1e3, 2e3

p = -alpha_obstacle * np.exp(-((x - x_obstacle)**2 / a_obstacle
                               + (y - y_obstacle)**2 / b_obstacle))

接下来,我们需要计算梯度(这是一个简单的有限差分,而不是解析地计算上面函数的导数):

代码语言:javascript
复制
# For the absolute values of "dx" and "dy" to mean anything, we'll need to
# specify the "cellsize" of our grid.  For purely visual purposes, though,
# we could get away with just "dy, dx = np.gradient(p)".
dy, dx = np.gradient(p, np.diff(y[:2, 0]), np.diff(x[0, :2]))

现在我们可以做一个“箭图”,然而,结果可能并不完全是你所期望的,因为网格上的每个点都会显示一个箭头:

代码语言:javascript
复制
fig, ax = plt.subplots()
ax.quiver(x, y, dx, dy, p)
ax.set(aspect=1, title='Quiver Plot')
plt.show()

让我们把箭头做大一点。最简单的方法是绘制每个第n个箭头,并让matplotlib处理自动缩放。我们将在这里使用每3个点。如果想要更少、更大的箭头,请将3更改为更大的整数。

代码语言:javascript
复制
# Every 3rd point in each direction.
skip = (slice(None, None, 3), slice(None, None, 3))

fig, ax = plt.subplots()
ax.quiver(x[skip], y[skip], dx[skip], dy[skip], p[skip])
ax.set(aspect=1, title='Quiver Plot')
plt.show()

好多了,但那些箭头还是很难看得见。一种更好的可视化方法可能是使用覆盖了黑色渐变箭头的图像绘图:

代码语言:javascript
复制
skip = (slice(None, None, 3), slice(None, None, 3))

fig, ax = plt.subplots()
im = ax.imshow(p, extent=[x.min(), x.max(), y.min(), y.max()])
ax.quiver(x[skip], y[skip], dx[skip], dy[skip])

fig.colorbar(im)
ax.set(aspect=1, title='Quiver Plot')
plt.show()

理想情况下,我们希望使用不同的色彩映射表或更改箭头颜色。我会把那部分留给你。您还可以考虑等高线图(ax.contour(x, y, p))或流线图(ax.streamplot(x, y, dx, dy)。我只想简单地举个例子:

代码语言:javascript
复制
fig, ax = plt.subplots()

ax.streamplot(x, y, dx, dy, color=p, density=0.5, cmap='gist_earth')

cont = ax.contour(x, y, p, cmap='gist_earth')
ax.clabel(cont)

ax.set(aspect=1, title='Streamplot with contours')
plt.show()

...And只是为了变得更花哨:

代码语言:javascript
复制
from matplotlib.patheffects import withStroke

fig, ax = plt.subplots()

ax.streamplot(x, y, dx, dy, linewidth=500*np.hypot(dx, dy),
              color=p, density=1.2, cmap='gist_earth')

cont = ax.contour(x, y, p, cmap='gist_earth', vmin=p.min(), vmax=p.max())
labels = ax.clabel(cont)

plt.setp(labels, path_effects=[withStroke(linewidth=8, foreground='w')])

ax.set(aspect=1, title='Streamplot with contours')
plt.show()

票数 46
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25342072

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档