如何绘制二元函数的3D图形

8

我正在尝试对多种类型的阻尼进行振动放大系数的3D绘图。为了让那些不知道它是什么的人简化问题,基本上你有三个变量:

  • beta,这个变量在0到无穷大之间变化,但是我想将其可视化为从0到3,在每0.2个间隔中。
  • 阻尼比d,在0到无限范围内变化,但是我想在0到1的范围内以0.1的间隔绘制它。
  • 最后一个变量nu,它是根据前两个变量变化的函数。

2D function, y is nu, x is beta

我的直觉告诉我应该用(X,Y,Z)=(beta,d,nu)绘制这个图表,但我刚开始使用这个库,对Python也不是很熟悉,只有在需要可视化或计算课堂问题时才会使用它。我尝试为beta和d创建了2个数组,但我不知道应该如何创建nu的数组,因为它取决于两者。

这是我现在拥有的代码片段:

    import math
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D


nu = []
b = [0.1 + i / 100 for i in range(0, 510)]
damp = [0.1 + i/10 for i in range(0,510)]

for d in damp:
    nu_new = []
    nu.append(nu_new)
    for beta in b:
        nu_new.append( math.sqrt(1+(2*d*beta)**2)/ math.sqrt((1-beta**2)**2+(2*d*beta)**2))

fig = plt.figure()
ax = Axes3D(fig)
ax.plot(b, d, nu)
plt.show()

我在试图绘制这个的过程中遇到了一些困难,如果你有任何建议,我会很高兴。

3个回答

13

如果你正在使用numpy,那么就不要使用math模块。Numpy内置了所有的数学函数,但它们在numpy数组上的运行效果更好。我们可以借助网格计算出所有b、d值下的nu。

网格可以接收2个1D数组,并返回2个2D数组,以便数组中的每个索引对应于原始1D数组中一对唯一元素。

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np

b = np.arange(0.2, 3.2, 0.2)
d = np.arange(0.1, 1.0, 0.1)

B, D = np.meshgrid(b, d)
nu = np.sqrt( 1 + (2*D*B)**2 ) / np.sqrt( (1-B**2)**2 + (2*D*B)**2)

fig = plt.figure()
ax = Axes3D(fig)
ax.plot_surface(B, D, nu)
plt.xlabel('b')
plt.ylabel('d')
plt.show()

这将产生: 在此输入图像描述

此外,3D 绘图往往会阻挡视野(因为尖峰会遮挡其后的内容)。我建议使用 pcolormesh 或 contourf 绘图。在后一种情况下,最后 6 行代码变为:

plt.contourf(B, D, nu)
plt.colorbar()
plt.xlabel('b')
plt.ylabel('d')
plt.show()

它产生: enter image description here


3

应该可以工作: 我不是Python专家,特别是这两个for循环可能非常不符合Python风格,但它完成了任务。

import math
import matplotlib.pyplot as plt
import numpy as np

b = np.arange(0.2, 3.2, 0.2)
d = np.arange(0.1, 1.0, 0.1)
nu = np.zeros( (b.size, d.size) )
counter_y = 0

for deta in d:
    counter_x = 0
    for beta in b:
        nu[counter_x, counter_y] = math.sqrt( 1 + (2*deta*beta)**2 ) / math.sqrt( (1-beta**2)**2 + (2*deta*beta)**2)
        counter_x += 1
    counter_y += 1

X, Y = np.meshgrid(d, b)

fig = plt.figure()
ax = fig.add_subplot(111, projection = '3d')
ax.plot_surface(X, Y, nu)

1
你需要做的是首先创建一个matplotlib图形
fig = plt.figure()
ax = Axes3D(fig)
ax.plot(b, d, nu)
plt.show()

此外,您的所有变量应该具有相同的大小。因此,您的变量 d 应该是与其他变量相同长度的数组。
如果将您的变量 d 转换为长度为 5100.1 数组,则会得到以下结果。
import math
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D


nu = []
b = [0.1 + i / 100 for i in range(0, 510)]
d = 0.1


for beta in b:
    nu.append( math.sqrt(1+(2*d*beta)**2)/ math.sqrt((1-beta**2)**2+(2*d*beta)**2))

#turned d into array of length 510 with 0.1 for each value
d = np.ones(510)*0.1


fig = plt.figure()
ax = Axes3D(fig)
ax.plot(b, d, nu)
plt.show()

你得到:

你得到:

enter image description here


谢谢!根据文档,这很有道理。但我也遇到了填充nu的问题。如果它随着两个变量而变化,我该如何填充它? - Bruno Ribeiro da Silva
这正是我想要的,但是对于多个d,问题在于我不知道如何为多个d创建多个nu。 - Bruno Ribeiro da Silva

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接