from matplotlib import pyplot as plt from matplotlib import animation from random import uniform import timeit class Particle: __slots__ = ('x', 'y', 'ang_speed') def __init__(self, x, y, ang_speed): self.x = x self.y = y self.ang_speed = ang_speed class ParticleSimulator: def __init__(self, particles): self.particles = particles def evolve(self, dt): timestep = 0.00001 nsteps = int(dt/timestep) for i in range(nsteps): for p in self.particles: norm = (p.x**2 + p.y**2)**0.5 v_x = (-p.y)/norm v_y = p.x/norm d_x = timestep * p.ang_speed * v_x d_y = timestep * p.ang_speed * v_y p.x += d_x p.y += d_y # def evolve(self, dt): # timestep = 0.00001 # nsteps = int(dt/timestep) # # First, change the loop order # for p in self.particles: # t_x_ang = timestep * p.ang_speed # for i in range(nsteps): # norm = (p.x**2 + p.y**2)**0.5 # p.x, p.y = p.x - t_x_ang*p.y/norm, p.y + t_x_ang * p.x/norm def visualize(simulator): X = [p.x for p in simulator.particles] Y = [p.y for p in simulator.particles] fig = plt.figure() ax = plt.subplot(111, aspect='equal') line, = ax.plot(X, Y, 'ro') # Axis limits plt.xlim(-1, 1) plt.ylim(-1, 1) # It will be run when the animation starts def init(): line.set_data([], []) return line, def animate(i): # We let the particle evolve for 0.1 time units simulator.evolve(0.01) X = [p.x for p in simulator.particles] Y = [p.y for p in simulator.particles] line.set_data(X, Y) return line, # Call the animate function each 10 ms anim = animation.FuncAnimation(fig, animate, init_func=init, blit=True, interval=10) plt.show() def test_visualize(): particles = [Particle( 0.3, 0.5, +1), Particle( 0.0, -0.5, -1), Particle(-0.1, -0.4, +3)] simulator = ParticleSimulator(particles) visualize(simulator) def test_evolve(): particles = [Particle( 0.3, 0.5, +1), Particle( 0.0, -0.5, -1), Particle(-0.1, -0.4, +3)] simulator = ParticleSimulator(particles) simulator.evolve(0.1) p0, p1, p2 = particles def fequal(a, b): return abs(a - b) < 1e-5 assert fequal(p0.x, 0.2102698450356825) assert fequal(p0.y, 0.5438635787296997) assert fequal(p1.x, -0.0993347660567358) assert fequal(p1.y, -0.4900342888538049) assert fequal(p2.x, 0.1913585038252641) assert fequal(p2.y, -0.3652272210744360) def benchmark(): particles = [Particle(uniform(-1.0, 1.0), uniform(-1.0, 1.0), uniform(-1.0, 1.0)) for i in range(100)] simulator = ParticleSimulator(particles) simulator.evolve(0.1) def timing(): result = timeit.timeit('benchmark()', setup='from __main__ import benchmark', number=10) # Result is the time it takes to run the whole loop print(result) result = timeit.repeat('benchmark()', setup='from __main__ import benchmark', number=10, repeat=3) # Result is a list of times print(result) def benchmark_memory(): particles = [Particle(uniform(-1.0, 1.0), uniform(-1.0, 1.0), uniform(-1.0, 1.0)) for i in range(100000)] simulator = ParticleSimulator(particles) simulator.evolve(0.001) if __name__ == '__main__': benchmark()