Python을 이용해서 2차원 평면 상에서 입자들이 충돌하는 시뮬레이션을 작성해 보았다. 아직 초보이기 때문에 다음 사이트를 참조하였다.
(참고 사이트: https://stackoverflow.com/questions/9401658/how-to-animate-a-scatter-plot)
입자들을 구역 안에 가둬 두고 운동 시키면서 충돌 시키는 프로그램이다. 충돌 시 입자의 속도는 충돌 방향으로만 영향을 받는다는 것을 이용해서 작성하였다.
탄성 계수 1
탄성 계수 0.9
탄성 계수: 1.1
아래는 코드
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
import pandas as pd
class ANI_Scatter(object):
"""An animated scatter plot using matplotlib.animations.FuncAnimation."""
def __init__(self, numpoints, area, e):
# 개체 수, 운동 영역
self.num = numpoints
self.area = area
self.e = e
# 위치
self.pos_x = np.random.rand(self.num) * self.area
self.pos_y = np.random.rand(self.num) * self.area
# 속도
self.v_x = np.random.randn(self.num) * 1
self.v_y = np.random.randn(self.num) * 1
# 통합
self.Data = pd.DataFrame(data={'Pos_x': self.pos_x, 'Pos_y': self.pos_y, 'V_x': self.v_x, 'V_y': self.v_y})
self.DataChange = self.Data.copy()
self.stream = self.data_stream()
# Setup the figure and axes...
self.fig, self.ax = plt.subplots()
# Then setup FuncAnimation.
self.ani = animation.FuncAnimation(self.fig, self.update, interval=1,
init_func=self.setup_plot, blit=True)
def setup_plot(self):
"""Initial drawing of the scatter plot."""
Data = next(self.stream)
color_list = [20.0/self.num*q for q in range(self.num)]
self.scat = self.ax.scatter(Data['Pos_x'], Data['Pos_y'], c=color_list, s=1000, marker='.', animated=True, vmin=0, vmax=20, cmap='jet')
self.ax.axis([-self.area/4, self.area*5/4, -self.area/4, self.area*5/4])
return self.scat,
def data_stream(self):
while True:
# 운동 업데이트
for i in range(self.num):
for j in range(self.num):
if j != i:
# 공 i의 위치
x_i = self.DataChange['Pos_x'][i]
y_i = self.DataChange['Pos_y'][i]
# 공 j의 위치
x_j = self.DataChange['Pos_x'][j]
y_j = self.DataChange['Pos_y'][j]
# 두 공 간의 거리 계산
dis = (x_i - x_j) ** 2 + (y_i - y_j) ** 2
# 거리가 기준 거리 내로 다가왔을 때
if np.sqrt(dis) < self.area/15:
# 각 공의 속도
vi_x = self.DataChange['V_x'][i]
vi_y = self.DataChange['V_y'][i]
vj_x = self.DataChange['V_x'][j]
vj_y = self.DataChange['V_y'][j]
# 두 공이 가까워질 때만 충돌식 계산
# (이렇게 안하면, 충돌하고 나서도 거리가 충분히 멀어지지 않을 경우 문제가 발생)
if ((x_j - x_i)*(vj_x - vi_x) < 0) or ((y_j - y_i)*(vj_y - vi_y) < 0):
# 충돌각 계산
angle = np.arctan2((x_j - y_i), (y_j - y_i))
# 속도를 충돌방향과 수평성분, 수직성분으로 나눔
v1h = vi_x*np.cos(angle)+vi_y*np.sin(angle)
v1v = vi_x*np.sin(angle)-vi_y*np.cos(angle)
v2h = vj_x*np.cos(angle)+vj_y*np.sin(angle)
v2v = vj_x*np.sin(angle)-vj_y*np.cos(angle)
# 충돌방향과 수직성분은 그대로
# 수평성분은 운동량 보존측과 탄성계수로부터 계산
e = self.e # 탄성계수
mi = 1 # i 입자의 질량
mj = 1 # j 입자의 질량
nv1h = (v2h - v1h) * (1 + e) / (mi / mj + 1) + v1h
nv2h = (v1h - v2h) * (1 + e) / (mj / mi + 1) + v2h
# 속도의 수평, 수직 성분을 화면상 x, y 성분으로 수정
self.DataChange['V_x'][i] = nv1h * np.cos(angle) + v1v * np.sin(angle)
self.DataChange['V_y'][i] = nv1h * np.sin(angle) - v1v * np.cos(angle)
self.DataChange['V_x'][j] = nv2h * np.cos(angle) + v2v * np.sin(angle)
self.DataChange['V_y'][j] = nv2h * np.sin(angle) - v2v * np.cos(angle)
for i in range(self.num):
# 위치 업데이트
self.DataChange['Pos_x'][i] = self.DataChange['Pos_x'][i] + self.DataChange['V_x'][i] * 0.5
self.DataChange['Pos_y'][i] = self.DataChange['Pos_y'][i] + self.DataChange['V_y'][i] * 0.5
# 사각형 벽 조건 (벽을 벗어나면 속도가 반대가 되도록)
if self.DataChange['Pos_x'][i] >= self.area:
self.DataChange['V_x'][i] = abs(self.DataChange['V_x'][i]) * -1
elif self.DataChange['Pos_x'][i] <= 0:
self.DataChange['V_x'][i] = abs(self.DataChange['V_x'][i])
if self.DataChange['Pos_y'][i] >= self.area:
self.DataChange['V_y'][i] = abs(self.DataChange['V_y'][i]) * -1
elif self.DataChange['Pos_y'][i] <= 0:
self.DataChange['V_y'][i] = abs(self.DataChange['V_y'][i])
yield self.DataChange
def update(self, i):
"""Update the scatter plot."""
Data = next(self.stream)
self.scat.set_offsets(Data[['Pos_x', 'Pos_y']].as_matrix())
return self.scat,
def show(self):
plt.xticks([])
plt.yticks([])
plt.title('Elasticity : ' + str(int(self.e*10)/10))
plt.show(block=False)
if __name__ == '__main__':
# numpoint: 입자 개수, area: 운동영역, e: 탄성계수
a = ANI_Scatter(numpoints=20, area=100, e=1.0)
a.show()
반응형
'공부 > Physics' 카테고리의 다른 글
| [Physics] 끈 이론(String theory) (0) | 2018.03.02 |
|---|---|
| [개념] Topology(위상수학)는 언제 사용하는가 (0) | 2018.02.23 |
| [영상] 동조화 현상 (5) | 2018.01.17 |
| [통계역학] 해석역학 (0) | 2017.11.01 |
| [공학] 칼만필터 (0) | 2017.06.20 |
댓글