pyOpenGLを使って分子動力学を可視化

以前ここで試したmatplotlibを使った簡単な分子動力学計算の可視化処理ですが、描画が遅いのでOpenGLを使って書き直してみた。python用にはPyOpenGLのパッケージが用意されている。結果だがとても速い!

■結果をgifアニメに落としたものが↓。
gifアニメだと実際の描画より遅いので感動が伝わりにくい。。。
openGLを使った可視化

import random
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *

from PIL import Image
from PIL import ImageOps

a  = 10
Dt = 0.1

#Define xy index
PX = 0
PY = 1
VX = 2
VY = 3
FX = 4
FY = 5

perticle_num = 1000
xy = [[0 for i in range(6)] for j in range(perticle_num)]
step = 1

def capture():
  global step
  step = step + 1
  pad_step = '{0:04d}'.format(step)
  print pad_step

  width = glutGet(GLUT_WINDOW_WIDTH)
  height = glutGet(GLUT_WINDOW_HEIGHT)

  glReadBuffer(GL_FRONT)
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
  data = glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE)

  image = Image.fromstring("RGBA", (width, height), data)
  image = ImageOps.flip(image)
  image.save("test"+pad_step+".png")

def integ():
  #verlet integration
  particle_num = len(xy)
  pnum = 0
  while pnum < particle_num:
    #update velocity
    xy[pnum][VX] = xy[pnum][VX] + 0.5*Dt*xy[pnum][FX]
    xy[pnum][VY] = xy[pnum][VY] + 0.5*Dt*xy[pnum][FY]

    #update position
    xy[pnum][PX] = xy[pnum][PX] + Dt*xy[pnum][VX]
    xy[pnum][PY] = xy[pnum][PY] + Dt*xy[pnum][VY]

    #boundary condition
    if xy[pnum][PX] > a:
       xy[pnum][PX] -= a
    if xy[pnum][PY] > a:
       xy[pnum][PY] -= a
    if xy[pnum][PX] < 0:
       xy[pnum][PX] += a
    if xy[pnum][PY] < 0:
       xy[pnum][PY] += a
    pnum += 1


def update():
    # If you want to get image...
    # capture()

    integ()
    nnum = 0
    while nnum < len(xy):
       glPointSize(3.0)
       glColor3f(0.3, 0.3, 1.0)
       glBegin(GL_POINTS)
       glVertex2d(xy[nnum][PX], xy[nnum][PY])
       glEnd()
       nnum = nnum + 1

def init_set():
  pnum = 0
  xv_sum = 0
  yv_sum = 0
  particle_num = len(xy)
  while pnum < particle_num:
    xy[pnum][PX] = 0  # 0 x-position 
    xy[pnum][PY] = 0  # 1 y-position
    xy[pnum][VX] = random.uniform(-1,1) # 2 x-velocity
    xy[pnum][VY] = random.uniform(-1,1) # 3 y-velocity
    xv_sum += xy[pnum][VX]
    yv_sum += xy[pnum][VY]
    xy[pnum][FX] = 0   # 0 x-force
    xy[pnum][FY] = 0   # 1 y-force
    pnum += 1

  xv_sum = xv_sum / particle_num
  yv_sum = yv_sum / particle_num
  pnum = 0
  while pnum < particle_num:
    xy[pnum][VX] = xy[pnum][VX] - xv_sum
    xy[pnum][VY] = xy[pnum][VY] - yv_sum
    pnum += 1
  #exit()

def draw():
    glClearColor(0.0, 0.0, 0.0, 0.0)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

    glLoadIdentity()

    glColor3f(1.0,1.0,0.0)
    gluLookAt(a/2, a/2, 20.0  ,a/2 ,a/2 ,0 , 0, 1.0, 0.0)

    glBegin(GL_LINE_LOOP)
    glVertex2d(0,0)
    glVertex2d(0,a)
    glVertex2d(a,a)
    glVertex2d(a,0)
    glEnd()

    update()
    glutSwapBuffers()

def init():
    glClearColor(0.7, 0.7, 0.7, 0.7)

def idle():
    glutPostRedisplay()

def reshape(w, h):
    glViewport(0, 0,w,h)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(30.0, w/h, 1.0, 100.0)
    glMatrixMode (GL_MODELVIEW)


if __name__ == "__main__":

    init_set()

    glutInitWindowPosition(50, 50);
    glutInitWindowSize(340, 340);
    glutInit(sys.argv)
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE )
    glutCreateWindow("pyOpenGL TEST")
    glutDisplayFunc(draw)
    glutReshapeFunc(reshape)
    init()

    glutIdleFunc(idle)
    glutMainLoop()

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA