我正在尝试使用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()
答案 0 :(得分: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()