-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathigsim.py
162 lines (119 loc) · 3.58 KB
/
igsim.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
"""
Simulation idealer Teilchen zur Modellierung idealer Gase
Moritz Smolka
Programmiert als Zusatzaufgabe fuer Physikalische Chemie
17.03.2015
Kern der Simulation: Definition der Teilchen, Schrittweise Simulation, Erhebung von Daten
"""
import math
import random
class Vector:
def __init__(self,x_=0,y_=0):
self.x = float(x_)
self.y = float(y_)
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __sub__(self, other):
return Vector(self.x - other.x, self.y - other.y)
def __mul__(self, other):
return Vector(self.x * other, self.y * other)
def __div__(self, other):
return Vector(self.x / other, self.y / other)
def length(self):
return math.sqrt(self.x*self.x + self.y*self.y)
def normalize(self):
if self.length() > 0:
return self / self.length()
else:
return Vector()
def dot(self,other):
return self.x * other.x + self.y * other.y
def __str__(self):
return "[%.2f,%.2f]" % (self.x,self.y)
class Particle:
radius = 3 #nm, wird nur benutzt wenn Simulation.particles_interact==True
mass = 1 #Nur fuer get_energy() relevant
def __init__(self):
self.pos = Vector()
self.vel = Vector()
def integrate(self,dt):
self.pos += self.vel * dt
def get_energy(self):
return 0.5 * self.mass * self.vel.length()**2
def get_nn(self,sim): #Nearest Neighbour Distance
min_dist = float("inf")
for part in sim.particles:
if part == self:
continue
if (part.pos - self.pos).length() < min_dist:
min_dist = (part.pos - self.pos).length()
return min_dist
class Simulation:
def __init__(self):
self.particles = []
self.width = 300 #nm
self.height = 150 #nm
self.wall_collisions = 0
self.particles_interact = False
def add(self,part):
self.particles.append(part)
def step(self,dt):
for part in self.particles:
part.integrate(dt)
self.constrain(part)
if self.particles_interact:
for i in range(0,len(self.particles)):
for j in range(i,len(self.particles)):
if i == j:
continue
self.collide(self.particles[i],self.particles[j])
def constrain(self,part):
collided = False
if part.pos.x > self.width:
part.pos.x = self.width
part.vel.x = -abs(part.vel.x)
collided = True
if part.pos.x < -self.width:
part.pos.x = -self.width
part.vel.x = abs(part.vel.x)
collided = True
if part.pos.y > self.height:
part.pos.y = self.height
part.vel.y = -abs(part.vel.y)
collided = True
if part.pos.y < -self.height:
part.pos.y = -self.height
part.vel.y = abs(part.vel.y)
collided = True
if collided:
self.wall_collisions += 1
def collide(self,a,b): #Partikel-Partikel Kollisionen
dist = a.pos - b.pos
if dist.length() == 0 or dist.length() > 2 * a.radius:
return #Keine Kollision
un = dist.normalize()
ut = Vector(-un.y,un.x)
van = un.dot(a.vel)
vat_n = ut * ut.dot(a.vel)
vbn = un.dot(b.vel)
vbt_n = ut * ut.dot(b.vel)
van_n = un * vbn
vbn_n = un * van
#print("Before",a.energy()+b.energy())
a.vel = van_n + vat_n
b.vel = vbn_n + vbt_n
#print("After",a.energy()+b.energy())
pen = (2*a.radius) - dist.length()
a.pos += un * (pen/2)
b.pos -= un * (pen/2)
#raw_input()
#raise SystemExit
def total_energy(self):
sum = 0
for part in self.particles:
sum += part.get_energy()
return sum
def avg_energy(self):
return self.total_energy() / len(self.particles)
def pressure(self):
return (self.wall_collisions)/float(self.width*2+self.height*2)