summaryrefslogtreecommitdiffstats
path: root/rutherford.py
diff options
context:
space:
mode:
Diffstat (limited to 'rutherford.py')
-rw-r--r--rutherford.py182
1 files changed, 182 insertions, 0 deletions
diff --git a/rutherford.py b/rutherford.py
new file mode 100644
index 0000000..5870404
--- /dev/null
+++ b/rutherford.py
@@ -0,0 +1,182 @@
+from __future__ import division
+from math import sqrt, ceil
+import random, pygame, sys
+import os
+import json
+from pygame.locals import *
+
+pygame.init()
+
+GRAY = ( 182, 182, 182)
+VIOLET = (150, 100, 190)
+RED = (150, 0, 0)
+GREEN = (0, 150, 0)
+BLUE = (30, 30, 180)
+VERYLIGHT = (210, 210, 210)
+BLACK = (0,0,0)
+WHITE = (255, 255, 255)
+
+TIME_STEP = 0.01
+
+K = 10000
+
+X_SCREEN_BORDER = 1200
+Y_SCREEN_BORDER = 800
+
+INITIAL_SPEED_X = 50
+INITIAL_SPEED_Y = 0
+INITIAL_Y = 400
+DEFAULT_OLD_X = 2 - INITIAL_SPEED_X*TIME_STEP
+DEFAULT_OLD_Y = INITIAL_Y - INITIAL_SPEED_Y*TIME_STEP
+
+def main():
+ #create the screen
+ window = pygame.display.set_mode((1200, 800))
+ colors = [GRAY, VIOLET, RED, GREEN, BLUE, VERYLIGHT, BLACK]
+
+ global INITIAL_SPEED_X
+ global INITIAL_SPEED_Y
+ global INITIAL_Y
+ #Initialize universe with some atoms
+ atom1 = Particle(1000, Vector2(500,500), Vector2(500,500), 20, BLUE)
+ atom2 = Particle(1, Vector2(2,400), Vector2(2-TIME_STEP*INITIAL_SPEED_X, INITIAL_Y- TIME_STEP*INITIAL_SPEED_Y), 1, RED)
+ universe = Universe([atom1, atom2])
+
+ screen = Screen(window, colors, universe)
+ screen.draw_surface()
+ keep_running = True
+ while keep_running:
+ screen.draw_surface()
+ universe.update_positions()
+ for event in pygame.event.get():
+ if event.type == pygame.QUIT:
+ keep_running = False
+ elif event.type == pygame.KEYUP:
+ if event.key == K_UP :
+ INITIAL_Y -= 10
+ elif event.key == K_DOWN:
+ INITIAL_Y += 10
+ elif event.key == K_RIGHT:
+ INITIAL_SPEED_X += 20
+ elif event.key == K_LEFT:
+ INITIAL_SPEED_X -= 20
+ if(INITIAL_SPEED_X < 0):
+ INITIAL_SPEED_X = 0
+ elif event.key == K_SPACE:
+ universe.add_particle(Particle(1, Vector2(2,INITIAL_Y),
+ Vector2(2-TIME_STEP*INITIAL_SPEED_X, INITIAL_Y- TIME_STEP*INITIAL_SPEED_Y),
+ 1, random.choice(colors)))
+
+ print "Pygame thread exited."
+
+
+
+
+class Screen:
+ def __init__(self, window, colors, universe):
+ self.communicates = []
+ self.communicates.append("Rutherford scattering")
+ self.window = window
+ self.universe = universe
+ self.colors = colors
+ self.color = WHITE
+
+ def change_color(self):
+ self.color = random.choice(self.colors)
+
+ def draw_universe(self):
+ self.draw_guide()
+ for particle in self.universe.particles:
+ self.draw_particle(particle)
+
+ def draw_particle(self, particle):
+ position = (int(ceil(particle.position.x)), int(ceil(particle.position.y)))
+ pygame.draw.circle(self.window, particle.color, position, 6+ int(particle.mass/100) )
+
+ def draw_guide(self):
+ pygame.draw.line(self.window, BLACK, (0, INITIAL_Y), (X_SCREEN_BORDER,INITIAL_Y), 2)
+
+ def draw_surface(self):
+ self.window.fill(self.color)
+ self.draw_universe()
+ for i, text in enumerate(self.communicates):
+ self.print_text(text, 20, 20 + i*20, (0, 0, 0), 30, self.window)
+ pygame.display.flip()
+
+ def print_text(self, text,xx,yy,color,text_size, screen):
+ font = pygame.font.SysFont(None,text_size)
+ ren = font.render(text,1,color)
+ screen.blit(ren, (xx,yy))
+
+
+class Vector2:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+
+
+class Particle:
+ def __init__(self, mass, position, old_position, charge, color):
+ self.mass = mass
+ self.position = position
+ self.old_position = old_position
+ self.acc = Vector2(0,0)
+ self.color = color
+ self.charge = charge
+
+
+class Universe:
+ def __init__(self, particles):
+ self.particles = particles
+ print("Universe has just been created!")
+
+ def update_accelerations(self):
+ for particle in self.particles:
+ particle.acc = Vector2(0,0)
+ for x in range(1, len(self.particles)):
+ accelerations = self.compute_acc(self.particles[x], self.particles[0])
+ self.particles[x].acc = accelerations[0]
+
+ def update_positions(self):
+ self.update_accelerations()
+ for particle in self.particles:
+ temporary_x = particle.position.x
+ temporary_y = particle.position.y
+ particle.position.x = 2 * particle.position.x - particle.old_position.x
+ particle.position.x += particle.acc.x * TIME_STEP * TIME_STEP
+ particle.position.y = 2 * particle.position.y - particle.old_position.y
+ particle.position.y += particle.acc.y * TIME_STEP * TIME_STEP
+ particle.old_position.x = temporary_x
+ particle.old_position.y = temporary_y
+ particle = self.limit_position(particle)
+
+ def limit_position(self, particle):
+ if(particle.position.x > X_SCREEN_BORDER or particle.position.y > Y_SCREEN_BORDER or
+ particle.position.x < 0 or particle.position.y < 0):
+ random_offset = random.randrange(-20, 20)
+ particle.position.x = 2
+ particle.old_position.x = 2 - INITIAL_SPEED_X*TIME_STEP
+ particle.position.y = INITIAL_Y + random_offset
+ particle.old_position.y = INITIAL_Y - INITIAL_SPEED_Y*TIME_STEP + random_offset
+ return particle
+
+ def compute_acc(self, particle1, particle2):
+ vertical_distance = particle1.position.y - particle2.position.y
+ horizontal_distance = particle1.position.x - particle2.position.x
+ distance = sqrt((vertical_distance)**2 + (horizontal_distance)**2)
+ force = particle1.charge * particle2.charge *K/distance**2
+ acc1x = force/particle1.mass*horizontal_distance/distance
+ acc1y = force/particle1.mass*vertical_distance/distance
+ acc2x = -force/particle2.mass*horizontal_distance/distance
+ acc2y = -force/particle2.mass*vertical_distance/distance
+ return [Vector2(acc1x, acc1y), Vector2(acc2x, acc2y)]
+
+ def add_particle(self, particle):
+ self.particles.append(particle)
+
+
+
+
+if __name__ == '__main__':
+ main() \ No newline at end of file