Lennard Jones粒子之间的相互作用。粒子移动到一点

时间:2015-04-22 13:28:16

标签: python pygame simulation physics scientific-computing

import numpy as np
import random
import pygame
background_colour = (255,255,255)
width, height = 300, 325
eps = 1
sigma = 1
dt = 0.05

class Particle():
    def __init__(self):
        self.x = random.uniform(0,400)
        self.y = random.uniform(0,500)
        self.vx = random.uniform(-.1,.1)
        self.vy = random.uniform(-.1,.1)
        self.fx = 0
        self.fy = 0
        self.m = 1
        self.size = 10
        self.colour = (0, 0, 255)
        self.thickness = 0

    def bounce(self):
        if self.x > width - self.size:
            self.x = 2*(width - self.size) - self.x

        elif self.x < self.size:
            self.x = 2*self.size - self.x

        if self.y > height - self.size:
            self.y = 2*(height - self.size) - self.y

        elif self.y < self.size:
            self.y = 2*self.size - self.y
    def getForce(self, p2):
        dx = self.x - p2.x
        dy = self.y - p2.y
        self.fx = 500*(-8*eps*((3*sigma**6*dx/(dx**2+dy**2)**4 - 6*sigma**12*dx/(dx**2+dy**2)**7)))
        self.fy = 500*(-8*eps*((3*sigma**6*dy/(dx**2+dy**2)**4 - 6*sigma**12*dy/(dx**2+dy**2)**7)))
        return self.fx, self.fy

    def verletUpdate(self,dt):
        self.x = self.x + dt*self.vx+0.5*dt**2*self.fx/self.m
        self.y = self.y + dt*self.vy+0.5*dt**2*self.fy/self.m
    def display(self):
       pygame.draw.circle(screen, self.colour, (int(self.x), int(self.y)), self.size, self.thickness)
screen = pygame.display.set_mode((width, height))
screen.fill(background_colour) 

partList = []
for k in range(10):
    partList.append(Particle())

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
    screen.fill(background_colour)

    for k, particle in enumerate(partList):
        for p2 in partList[k+1:]:
            particle.getForce(p2)
        particle.verletUpdate(dt)
        particle.bounce()
        particle.display()

    pygame.display.flip()
pygame.quit()

我的代码是否正确?我试图用Lennard Jones力量模拟2D移动中的粒子。我认为计算力是可行的,但为什么我的粒子移动到一点?偶尔我也会收到错误OverflowError: Python int too large to convert to C long任何建议都会有用。

1 个答案:

答案 0 :(得分:0)

我无法评论模拟的物理特性,但就显示而言,以下是我的观察:

您的粒子移动到一个点,因为verletUpdate中代码中x和y参数的更新条件正在缓慢移动到显示区域之外的值。也适用于导致错误的int()函数范围之外的值。您可以使用以下语句看到:

def verletUpdate(self,dt):
    self.x = self.x + dt*self.vx+0.5*dt**2*self.fx/self.m
    self.y = self.y + dt*self.vy+0.5*dt**2*self.fy/self.m
    print self.x
    print self.y

示例输出:

290.034892392
9.98686293664
290.028208837
9.99352484332
-2.55451579742e+19
1.12437640586e+19

同样,它们饱和并且通过迭代,更新变得越来越小:

def display(self):
          print ' %s + %s '%(self.x,self.y)
          pygame.draw.circle(screen, self.colour, (int(self.x), int(self.y)), self.size, self.thickness)

输出:

 10.0009120033 + 10.0042647307 
 10.0009163718 + 10.0000322065 
 10.0009120033 + 10.0042647307 
 10.0009163718 + 10.0000322065 
 ...
 10.0009163718 + 10.0000322065 
 10.0009120033 + 10.0042647307 
 10.0009163718 + 10.0000322065 

这也是您的退回功能和限制检查无效的原因。经过大量的迭代后,你的self.x和self.y远远超过int()的限制。

代码看起来很好,但是您可以通过在绘制线上方添加一些检查来消除溢出错误。例如,我再次随机初始化它们以模拟屏幕上的粒子和我们跟踪新的粒子。随意改变它。

   def display(self):
          if(self.x<0 or self.x>height):
              self.__init__()
              print "reset"
          if(self.y<0 or self.y>width):
              self.__init__()
              print "reset"
          print ' %s + %s '%(self.x,self.y)
          pygame.draw.circle(screen, self.colour, (int(self.x), int(self.y)), self.size, self.thickness)

同样在某一点上,您将数组称为[k + 1:],并且寻址零元素会导致除以零错误。你可能想看一下。