LoginSignup
8
8

More than 5 years have passed since last update.

matplotlibでキャビティ流れを可視化し、gifアニメで保存する

Last updated at Posted at 2015-06-06

を見て、キャビティ流れの書き方がわかったが、アニメーションしないので物足りない。

最終結果だけを表示するコードは以下。(元ネタではiPython Notebookを使ってやっている)

cavorg.py
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation

nx = 41
ny = 41
nt = 5
nit=50
c = 1
dx = 2.0/(nx-1)
dy = 2.0/(ny-1)
x = np.linspace(0,2,nx)
y = np.linspace(0,2,ny)
X,Y = np.meshgrid(x,y)

rho = 1
nu = .1
dt = .001

u = np.zeros((ny, nx))
v = np.zeros((ny, nx))
p = np.zeros((ny, nx)) 
b = np.zeros((ny, nx))


def buildUpB(b, rho, dt, u, v, dx, dy):

    b[1:-1,1:-1]=rho*(1/dt*((u[1:-1,2:]-u[1:-1,0:-2])/(2*dx)+(v[2:,1:-1]-v[0:-2,1:-1])/(2*dy))-\
                      ((u[1:-1,2:]-u[1:-1,0:-2])/(2*dx))**2-\
                      2*((u[2:,1:-1]-u[0:-2,1:-1])/(2*dy)*(v[1:-1,2:]-v[1:-1,0:-2])/(2*dx))-\
                      ((v[2:,1:-1]-v[0:-2,1:-1])/(2*dy))**2)

    return b

def presPoisson(p, dx, dy, b):
    pn = np.empty_like(p)
    pn = p.copy()

    for q in range(nit):
        pn = p.copy()
        p[1:-1,1:-1] = ((pn[1:-1,2:]+pn[1:-1,0:-2])*dy**2+(pn[2:,1:-1]+pn[0:-2,1:-1])*dx**2)/\
                        (2*(dx**2+dy**2)) -\
                        dx**2*dy**2/(2*(dx**2+dy**2))*b[1:-1,1:-1]

        p[-1,:] =p[-2,:] ##dp/dy = 0 at y = 2
        p[0,:] = p[1,:]  ##dp/dy = 0 at y = 0
        p[:,0]=p[:,1]    ##dp/dx = 0 at x = 0
        p[:,-1]=0        ##p = 0 at x = 2

    return p

def cavityFlow(nt, u, v, dt, dx, dy, p, rho, nu):
    un = np.empty_like(u)
    vn = np.empty_like(v)
    b = np.zeros((ny, nx))

    for n in range(nt):
        un = u.copy()
        vn = v.copy()

        b = buildUpB(b, rho, dt, u, v, dx, dy)
        p = presPoisson(p, dx, dy, b)

        u[1:-1,1:-1] = un[1:-1,1:-1]-\
                        un[1:-1,1:-1]*dt/dx*(un[1:-1,1:-1]-un[1:-1,0:-2])-\
                        vn[1:-1,1:-1]*dt/dy*(un[1:-1,1:-1]-un[0:-2,1:-1])-\
                        dt/(2*rho*dx)*(p[1:-1,2:]-p[1:-1,0:-2])+\
                        nu*(dt/dx**2*(un[1:-1,2:]-2*un[1:-1,1:-1]+un[1:-1,0:-2])+\
                        dt/dy**2*(un[2:,1:-1]-2*un[1:-1,1:-1]+un[0:-2,1:-1]))

        v[1:-1,1:-1] = vn[1:-1,1:-1]-\
                        un[1:-1,1:-1]*dt/dx*(vn[1:-1,1:-1]-vn[1:-1,0:-2])-\
                        vn[1:-1,1:-1]*dt/dy*(vn[1:-1,1:-1]-vn[0:-2,1:-1])-\
                        dt/(2*rho*dy)*(p[2:,1:-1]-p[0:-2,1:-1])+\
                        nu*(dt/dx**2*(vn[1:-1,2:]-2*vn[1:-1,1:-1]+vn[1:-1,0:-2])+\
                        (dt/dy**2*(vn[2:,1:-1]-2*vn[1:-1,1:-1]+vn[0:-2,1:-1])))

        u[0,:] = 0
        u[:,0] = 0
        u[:,-1] = 0
        u[-1,:] = 1    #set velocity on cavity lid equal to 1
        v[0,:] = 0
        v[-1,:]=0
        v[:,0] = 0
        v[:,-1] = 0

    return u, v, p

fig = plt.figure(figsize=(11,7), dpi=100)
u, v, p = cavityFlow(nt, u, v, dt, dx, dy, p, rho, nu)

plt.contourf(X,Y,p,alpha=0.5)
plt.colorbar()
plt.contour(X,Y,p)
plt.quiver(X[::2,::2],Y[::2,::2],u[::2,::2],v[::2,::2])
plt.xlabel('X')
plt.ylabel('Y')
plt.show()

matplotlib.animationを使うとgifアニメが作れるらしいので挑戦してみたがうまくいかなかった。理由を以下で説明する。

gifアニメは、imagemagickが入っていれば作れる。これは以下参照。
http://kiito.hatenablog.com/entry/2013/11/27/233507

アニメーションさせるための具体的な方法は以下。

アニメーションをさせる方法は二通りのやり方があるようです。
animation.ArtistAnimation
...事前に用意してあるデータを描画
animation.FuncAnimation
...随時データを更新する

from http://cflat-inc.hatenablog.com/entry/2014/03/17/214719

その他の例
http://qiita.com/HirofumiYashima/items/5864fb9384053b77cf6f
http://d.hatena.ne.jp/xef/20120629/p2
http://stackoverflow.com/questions/24166236/add-text-to-image-animated-with-matplotlib-artistanimation

最初のシミュレーションコードはcavityFlow()の中でforループを回しているので、ループごとにデータを吐き出して、ArtistAnimationで描画しようと思ったのだが、描画用データの配列にcontourfを渡すとバグが出る。これは他のところでも報告されているのだが、対応されているのかどうかわからない。

http://matplotlib.1069221.n5.nabble.com/Matplotlib-1-1-0-animation-vs-contour-plots-td18703.html
http://stackoverflow.com/questions/23070305/how-can-i-make-an-animation-with-contourf

とりあえずArtistAnimationではなくFuncAnimationでやればcontourfでもアニメになるらしいが、ArtistAnimationでもできるよという情報もある。
contourfを除いて、流線だけ描写してみたところ無事作成できたので、これはやはりcontourfが原因のバグっぽい。

8
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
8