【问题标题】:Animation of a 3D surface from calculated matrices来自计算矩阵的 3D 表面动画
【发布时间】:2017-01-19 14:36:05
【问题描述】:

我正在尝试对 Jacobi 迭代方法生成的 3D 表面进行动画处理,每次迭代后都会生成一个矩阵 UF 并将其存储在列表中 UFK 我能够自己绘制每次迭代,但我想要创建一个动画,显示从凹面到平面平滑的演变和收敛。谢谢。

import numpy as np 
import pandas as pd
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import matplotlib.animation as animation
%matplotlib notebook

Nx = 15        
Ny = 15         
tol = 1e-3      
err = 1        
k = 0         

Uy0 = 200*np.ones((1,Nx)) # Boundry condition at y=0 # lower boundry
UNy = 200*np.ones((1,Nx)) # Boundry condition at y=Ny # Upper boundary
Ux0 = 200*np.ones(Ny) # Boundry condition at x=0 # left boundry 
UNx = 200*np.ones(Ny) # Boundry condition at x=Nx # Right boundary 
# initial the whole matrix: the value at the interior nodes 
U = np.zeros((Ny,Nx))
#Adding boundry conditions to the matrix 
U[0] = UNy
U[Ny-1] = Uy0
U[:,Nx-1] = UNx
U[:,0]= Ux0
# Iterate Jacobi method  
UFK=[]
UFK.append(U.copy())
NFK=[]
UF=U.copy()

while True:
    k=k+1 
    for i in range (1,Nx-1):
        for j in range (1,Ny-1):
            UF[j,i] = (UF[j+1,i]+UF[j,i+1]+UF[j-1,i]+UF[j,i-1])*0.25 #the matrix i want to plot after each iteration 
    UFK.append(UF.copy())
    H = UFK[-1]-UFK[-2]
    N = np.linalg.norm(H)
    NFK.append(N)
    if N <= tol:
        break

def data(t,UFK,surf):
    for t in range(0,k-1):
        L = UFK[t]
        ax.clear()
        surf = ax.plot_surface(XX, YY, L, rstride=1, cstride=1, cmap=cm.coolwarm, linewidth=0, antialiased=False)
    return surf

fig = plt.figure()
ax = fig.gca(projection='3d')
X = np.arange(0, Nx)
Y = np.arange(0, Ny)
XX,YY = np.meshgrid(X, Y)
surf = ax.plot_surface(XX, YY, UFK[0],rstride=1, cstride=1, cmap=cm.coolwarm, linewidth=0, antialiased=False)
ax.set_zlim(0, 200)
ax.zaxis.set_major_locator(LinearLocator(10))
fig.colorbar(surf, shrink=0.5, aspect=10)
ax.set_xlabel('X nodes - Axis')
ax.set_ylabel('Y nodes - Axis')
ax.set_zlabel('Value')



ani = animation.FuncAnimation(fig, data, fargs=(UFK,surf), interval=10, repeat=True )
plt.show()

【问题讨论】:

  • 问题缺乏清晰的问题描述,代码无法运行。为了在此处发布问题,您需要准确地陈述问题并最好提供可验证的示例代码。
  • 感谢您的回复。我添加了代码的初始化部分,我试图为 Z 值是矩阵UFK [i] 的绘图设置动画。 while 循环中的每次迭代都会生成一个存储在列表UFK 中的矩阵,它们是 Z 坐标。如果我绘制一个矩阵surf = ax.plot_surface(XX, YY, UFK[5],rstride=1, cstride=1, cmap=cm.coolwarm, linewidth=0, antialiased=False) 它可以工作,但我希望所有迭代在动画图中一个接一个地显示。
  • 我想做这样的事情 [nugnux.my.id/2015/11/…

标签: python numpy matplotlib


【解决方案1】:

首先,对animation.FuncAnimation 的调用必须在plt.show() 之前发生。

其次,您不需要将参数UFK,surf 提供给动画函数。

第三,data 内部的循环针对每个动画步骤运行,因此您最终会得到相同的图。摆脱那个循环。

第四,将动画限制在你计算出的矩阵数量内。

这是一个工作代码:

import numpy as np 
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator
import matplotlib.animation as animation


Nx = 15        
Ny = 15         
tol = 1e-3      
err = 1        
k = 0         

Uy0 = 200*np.ones((1,Nx)) # Boundry condition at y=0 # lower boundry
UNy = 200*np.ones((1,Nx)) # Boundry condition at y=Ny # Upper boundary
Ux0 = 200*np.ones(Ny) # Boundry condition at x=0 # left boundry 
UNx = 200*np.ones(Ny) # Boundry condition at x=Nx # Right boundary 
# initial the whole matrix: the value at the interior nodes 
U = np.zeros((Ny,Nx))
#Adding boundry conditions to the matrix 
U[0] = UNy
U[Ny-1] = Uy0
U[:,Nx-1] = UNx
U[:,0]= Ux0
# Iterate Jacobi method  
UFK=[]
UFK.append(U.copy())
NFK=[]
UF=U.copy()

while True:
    k=k+1 
    for i in range (1,Nx-1):
        for j in range (1,Ny-1):
            UF[j,i] = (UF[j+1,i]+UF[j,i+1]+UF[j-1,i]+UF[j,i-1])*0.25 #the matrix i want to plot after each iteration 
    UFK.append(UF.copy())
    H = UFK[-1]-UFK[-2]
    N = np.linalg.norm(H)
    NFK.append(N)
    if N <= tol:
        break

def data(t):
    # remove for loop here
    L = UFK[t]
    ax.clear()
    surf = ax.plot_surface(XX, YY, L, rstride=1, cstride=1, cmap=cm.coolwarm, linewidth=0, antialiased=False)
    ax.set_zlim([0,200]) # set zlim to be always the same for every frame


fig = plt.figure()
ax = fig.gca(projection='3d')
X = np.arange(0, Nx)
Y = np.arange(0, Ny)
XX,YY = np.meshgrid(X, Y)
surf = ax.plot_surface(XX, YY, UFK[0],rstride=1, cstride=1, cmap=cm.coolwarm, linewidth=0, antialiased=False)
ax.set_zlim(0, 200)
ax.zaxis.set_major_locator(LinearLocator(10))
fig.colorbar(surf, shrink=0.5, aspect=10)
ax.set_xlabel('X nodes - Axis')
ax.set_ylabel('Y nodes - Axis')
ax.set_zlabel('Value')

ani = animation.FuncAnimation(fig, data, len(UFK), interval=50, repeat=True )
plt.show()

【讨论】:

  • 如果这三点是您的代码中唯一的问题,在您提供minimal reproducible example 之前无法验证。
  • 我还将这些更改应用于您的代码并将它们粘贴到我的答案中。对我来说,这是可行的。
  • 它工作非常感谢你我感谢你的帮助,它一定是 Z 轴限制。我可以从不同的帧开始动画吗?我不希望它从UFK[0] 开始,例如我希望它从 100 开始。我在 Matplotlib 中看到了一些关于 init_func 的内容。否则我如何将帧从 len(UFK) 更改为范围。谢谢
  • 请查看FuncAnimation documentation。 frames 参数接受一个整数,就像在这种情况下 len(UFK) 一样,但也像一个列表一样是一个可迭代的。如果你想从 100 开始,你可以使用np.arange(100, len(UFK), 1)
  • 感谢您的帮助和耐心,它运行良好 ufortunatlly 当我尝试使用 range(100, len(UFK) 时,我想念理解 Matplotlib 文档中的解释,因为它不起作用所以我尝试使用 @ 失败987654334@ 和gen_function()。再次感谢您,我将尝试找到一些示例来学习如何使用 init_funcgen_function() 这对我来说很重要,因为我经常需要这种类型的动画,而且我是 python 的初学者。
猜你喜欢
  • 1970-01-01
  • 2012-07-30
  • 2012-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-04
  • 1970-01-01
  • 2011-03-30
相关资源
最近更新 更多