从计算的矩阵中动画3D表面

时间:2017-01-19 14:36:06

标签: python numpy matplotlib

我正在尝试使用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()

1 个答案:

答案 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()