Zoom je heel ver in, dan zie je deeltjes rond vliegen. Elk met een eigen massa, een eigen snelheid en richting. De deeltjes botsen onderling, wisselen energie uit. We zouden op basis van een botsingsmodel van deeltjes iets moeten kunnen leren over thermodynamica. In de thermodynamica gaat het dan om heel veel deeltjes. Maar laten we beginnen met twee botsende ‘deeltjes’.
Je raadt het misschien al... deze simulatie gaan we na bouwen! Daarbij maken we gebruik van Python classes uit het vorige hoofdstuk en de basics van simulaties geleerd in Q1. Zorg er dus voor dat je weet hoe dit werkt! We maken ook gebruik van plotten, en daarbovenop een animatie. Hoe de animatie precies werkt en hoe je die zelf maakt hoef je niet te weten. Je zou wel in staat moeten zijn de code te lezen.
In de onderstaande cell maken we de ParticleClass aan, en geven we enkele parameters van onze simulatie op.
# Importeren van libraries
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import time
import itertools
# Maken van de class
class ParticleClass:
def __init__(self, m, v, r, R):
self.m = m
self.v = np.array(v, dtype=float)
self.r = np.array(r, dtype=float)
self.R = np.array(R, dtype=float)
def update_position(self):
self.r += self.v * dt
# Simulation parameters
dt = 0.1 # tijd stap
num_steps = 500 # aantal te nemen stappen
particle = ParticleClass(m=1.0, v=[5.0, 0], r=[0.0, 0.0], R=1.0) # het maken van ons deeltje
We hebben nu een deeltje met massa, een snelheid, een begin positie en een straal. We hebben ook al de stapgrootte bepaald!
We willen de beweging van dat deeltje straks bestuderen en moeten dus een plot maken:
# Creeer een figuur en de assen
fig, ax = plt.subplots()
ax.set_xlim(-10, 10)
ax.set_ylim(-10, 10)
ax.set_aspect('equal')
ax.set_title("Animatie")
ax.set_xlabel("x")
ax.set_ylabel("y")
# Toon het deeltje als een rode stip
dot, = ax.plot([], [], 'ro', markersize=10); # semicolon to suppress output

Bij het aanmaken van ons deeltje hebben we het deeltje een beginpositie en snelheid mee gegeven. Als we dan per tijdstap de positie bepalen en deze laten plotten en die plots achter elkaar plakken, dan krijgen we een animatie van het deeltje. Met FuncAnimation wordt die animatie voor ons gedaan.
# Initialisieren van de functie voor de animatie
def init():
dot.set_data([], [])
return dot,
# Updaten van de functie voor elk frame
def update(frame):
particle.update_position()
dot.set_data([particle.r[0]], [particle.r[1]])
return dot,
# Creeer de animatie
ani = FuncAnimation(fig, update, frames=range(200), init_func=init, blit=True, interval=50)
# Omdat we werken met Jup. Notebooks (en niet een .py file)
from IPython.display import HTML
HTML(ani.to_jshtml())
Frames in FuncAnimation verwijst naar het totaal aantal frames dat gebruikt wordt.
Interval naar de snelheid van de animatie, nl. 50 milliseconden ofwel 20 frames per seconde.
Merk op dat als we de laatste cel opnieuw runnen, het deeltje zich niet in de oorsprong bevindt. Dat is een ‘eigenaardigheid’ van Jupyter Notebooks. Het is nu beter om alle code in één cel te plaatsen (hieronder gedaan voor je), zodat we ervoor zorgen dat het deeltje altijd in de oorsprong begint.
# Simulation parameters
dt = 0.1 # time step
num_steps = 500 # number of time steps
particle = ParticleClass(m=1.0, v=[5.0, 0], r=[0.0, 0.0],R=1.0)
# Create the figure and axis
fig, ax = plt.subplots()
ax.set_xlim(-10, 10)
ax.set_ylim(-10, 10)
ax.set_aspect('equal')
ax.set_title("Particle Animation")
ax.set_xlabel("x")
ax.set_ylabel("y")
# Create the particle as a red dot
dot, = ax.plot([], [], 'ro', markersize=10)
# Initialization function for animation
def init():
dot.set_data([], [])
return dot,
# Update function for each frame
def update(frame):
particle.update_position()
dot.set_data([particle.r[0]], [particle.r[1]])
return dot,
# Create animation
ani = FuncAnimation(fig, update, frames=range(200), init_func=init, blit=True, interval=50)
# For Jupyter notebook:
from IPython.display import HTML
HTML(ani.to_jshtml())

Een van de dingen die je kunt opmerken, is dat het deeltje niet in zijn doos blijft.
#doorlopende doos
#your code/answer
class ParticleClass:
def __init__(self, m, v, r, R):
self.m = m
self.v = np.array(v, dtype=float)
self.r = np.array(r, dtype=float)
self.R = np.array(R, dtype=float)
def update_position(self):
self.r += self.v * dt
self.r = self.r % 20 #remainder van de positie gedeeld door de lengte van het doosje (20) nemen, zodat er een doorloopt in de doos
# Simulation parameters
dt = 0.1 # time step
num_steps = 500 # number of time steps
particle = ParticleClass(m=1.0, v=[5.0, 0], r=[0.0, 0.0],R=1.0)
# Create the figure and axis
fig, ax = plt.subplots()
ax.set_xlim(0, 20) #x-as van 0 naar 20 laten lopen, zodat met de remainder van de positie gedeeld door
#het lengte van het doosje gebruikt kan worden om het een doorlopend doosje te maken
ax.set_ylim(-10, 10)
ax.set_aspect('equal')
ax.set_title("Particle Animation")
ax.set_xlabel("x")
ax.set_ylabel("y")
# Create the particle as a red dot
dot, = ax.plot([], [], 'ro', markersize=10)
# Initialization function for animation
def init():
dot.set_data([], [])
return dot,
# Update function for each frame
def update(frame):
particle.update_position()
dot.set_data([particle.r[0]], [particle.r[1]])
return dot,
# Create animation
ani = FuncAnimation(fig, update, frames=range(200), init_func=init, blit=True, interval=50)
# For Jupyter notebook:
from IPython.display import HTML
HTML(ani.to_jshtml())

# doos met harde wanden
#your code/answer
class ParticleClass:
def __init__(self, m, v, r, R):
self.m = m
self.v = np.array(v, dtype=float)
self.r = np.array(r, dtype=float)
self.R = np.array(R, dtype=float)
def update_position(self):
#als het deeltje buiten de randen op x=0 en x=20 komt, keert de snelheid om
if particle.r[0] <= 0 or particle.r[0] >= 20:
self.v = -self.v
self.r += self.v * dt
# Simulation parameters
dt = 0.1 # time step
num_steps = 500 # number of time steps
particle = ParticleClass(m=1.0, v=[-5.0, 0], r=[0.0, 0.0],R=1.0)
# Create the figure and axis
fig, ax = plt.subplots()
ax.set_xlim(0, 20)
ax.set_ylim(-10, 10)
ax.set_aspect('equal')
ax.set_title("Particle Animation")
ax.set_xlabel("x")
ax.set_ylabel("y")
# Create the particle as a red dot
dot, = ax.plot([], [], 'ro', markersize=10)
# Initialization function for animation
def init():
dot.set_data([], [])
return dot,
# Update function for each frame
def update(frame):
particle.update_position()
dot.set_data([particle.r[0]], [particle.r[1]])
return dot,
# Create animation
ani = FuncAnimation(fig, update, frames=range(200), init_func=init, blit=True, interval=50)
# For Jupyter notebook:
from IPython.display import HTML
HTML(ani.to_jshtml())

class ParticleClass:
def __init__(self, m, v, r, R):
self.m = m
self.v = np.array(v, dtype=float)
self.r = np.array(r, dtype=float)
self.R = np.array(R, dtype=float)
def update_position(self):
self.v[self.r<=-10] = -self.v[self.r<=-10] #de snelheid van het deeltje als word in de x of y richting omgedraaid als het buiten de rand op x=-10 of y=-10
self.v[self.r>=10] = -self.v[self.r>=10] #de snelheid van het deeltje als word in de x of y richting omgedraaid als het buiten de rand op x=10 of y=10
self.r += self.v * dt
# Simulation parameters
dt = 0.1 # time step
num_steps = 500 # number of time steps
particle = ParticleClass(m=1.0, v=[5.0, 3], r=[0.0, 0.0],R=1.0)
# Create the figure and axis
fig, ax = plt.subplots()
ax.set_xlim(-10, 10)
ax.set_ylim(-10, 10)
ax.set_aspect('equal')
ax.set_title("Particle Animation")
ax.set_xlabel("x")
ax.set_ylabel("y")
# Create the particle as a red dot
dot, = ax.plot([], [], 'ro', markersize=10)
# Initialization function for animation
def init():
dot.set_data([], [])
return dot,
# Update function for each frame
def update(frame):
particle.update_position()
dot.set_data([particle.r[0]], [particle.r[1]])
return dot,
# Create animation
ani = FuncAnimation(fig, update, frames=range(200), init_func=init, blit=True, interval=50)
# For Jupyter notebook:
from IPython.display import HTML
HTML(ani.to_jshtml())

Laten we teruggaan naar ons deeltje. Er is een functie om de positie bij te werken, hoewel de snelheid hetzelfde lijkt te blijven... kunnen we de snelheid veranderen door (bijvoorbeeld) de versnelling door de zwaartekracht?
# Maken van de class met versnelling
class ParticleClass:
def __init__(self, m, v, r, R):
self.m = m # mass of the particle
self.v = np.array(v, dtype=float) # velocity vector
self.r = np.array(r, dtype=float) # position vector
self.R = np.array(R, dtype=float) # radius of the particle
def update_position(self):
self.r += self.v * dt
def update_velocity(self, a):
# om het dempening effect van de numerieke intergratie tegen te gaan wordt eerst de helft van de
# acceleratie gebruikt, dan word gechekt voor botsingen met de randen en dan word weer de helft van de acceleratie gebruikt
self.v += 0.5*a*dt
self.v[self.r<=-10] = -self.v[self.r<=-10] #de snelheid van het deeltje als word in de x of y richting omgedraaid als het buiten de rand op x=-10 of y=-10
self.v[self.r>=10] = -self.v[self.r>=10] #de snelheid van het deeltje als word in de x of y richting omgedraaid als het buiten de rand op x=10 of y=10
self.v += 0.5*a*dt
#your code/answer
# Simulation parameters
dt = 0.1 # time step
num_steps = 500 # number of time steps
a = np.array([0, -9.81]) #versnelingsveld van a_x=0 en a_y=-9.81
particle = ParticleClass(m=1.0, v=[0, 0], r=[0.0, 0.0],R=1.0)
# Create the figure and axis
fig, ax = plt.subplots()
ax.set_xlim(-10, 10)
ax.set_ylim(-10, 10)
ax.set_aspect('equal')
ax.set_title("Particle Animation")
ax.set_xlabel("x")
ax.set_ylabel("y")
# Create the particle as a red dot
dot, = ax.plot([], [], 'ro', markersize=10)
# Initialization function for animation
def init():
dot.set_data([], [])
return dot,
# Update function for each frame
def update(frame):
particle.update_velocity(a) #snelheid aanpassen op basis van de versnelling en botsingen met de muren
particle.update_position()
dot.set_data([particle.r[0]], [particle.r[1]])
return dot,
# Create animation
ani = FuncAnimation(fig, update, frames=range(200), init_func=init, blit=True, interval=50)
# For Jupyter notebook:
from IPython.display import HTML
HTML(ani.to_jshtml())

Een optie om de simulatie te verbeteren is de tijdstap kleiner te maken, maar dan hebben we ook meer geduld meer nodig - het aantal berekeningen schaalt met . Een tweede optie is een meer directe oplossing: We weten dat en daarom weten we ook de bewegingsvergelijking van het deeltje!
Daarnaast willen we graag weten waar het deeltje is geweest, dat is in onderstaande code toegevoegd.
# Maken van de class met versnelling
class ParticleClass:
def __init__(self, m, v, r, R):
self.m = m
self.v = np.array(v, dtype=float)
self.r = np.array(r, dtype=float)
self.R = np.array(R, dtype=float)
def update_position(self):
self.r += self.v * dt + 1/2 * a * dt**2
def update_velocity(self, a):
self.v += a*dt #eerst snelheid aanpassen op basis van de acceleratie, anders gaat het deeltje raar doen bij de randen
self.v[self.r<=-10] = -self.v[self.r<=-10] #de snelheid van het deeltje als word in de x of y richting omgedraaid als het buiten de rand op x=-10 of y=-10
self.v[self.r>=10] = -self.v[self.r>=10] #de snelheid van het deeltje als word in de x of y richting omgedraaid als het buiten de rand op x=10 of y=10
# Simulation parameters
dt = 0.1
num_steps = 500
particle = ParticleClass(m=1.0, v=[0, 0], r=[0.0, 0.0],R=1.0)
a = np.array([0.0, -5.0])
track_x = np.zeros(num_steps)
track_y = np.zeros(num_steps)
# creëren van de plot en de assen
fig, ax = plt.subplots()
ax.set_xlim(-10, 10)
ax.set_ylim(-10, 10)
ax.set_aspect('equal')
ax.set_title("Particle Animation")
ax.set_xlabel("x")
ax.set_ylabel("y")
track_line, = ax.plot([], [], 'r--', linewidth=1)
# creeëren van ons rode deeltje
dot, = ax.plot([], [], 'ro', markersize=10);
# initializeren van onze functie voor de animatie
def init():
dot.set_data([], [])
return dot,
# Update function for each frame
def update(frame):
particle.update_velocity(a)
particle.update_position()
track_x[frame] = particle.r[0]
track_y[frame] = particle.r[1]
track_line.set_data(track_x, track_y)
dot.set_data([particle.r[0]], [particle.r[1]])
return dot, track_line
# Create animation
ani = FuncAnimation(fig, update, frames=range(200), init_func=init, blit=True, interval=50)
# For Jupyter notebook:
from IPython.display import HTML
HTML(ani.to_jshtml())

We hebben steeds slechts gewerkt met een enkel deeltje. Maar om de simulatie uit het filmpje te maken, hebben we twee deeltjes nodig.
#your code/answer
# Maken van de class met versnelling
class ParticleClass:
def __init__(self, m, v, r, R, c):
self.m = m
self.v = np.array(v, dtype=float)
self.r = np.array(r, dtype=float)
self.R = np.array(R, dtype=float)
self.c = c #the collor of the particle
def update_position(self):
self.r += self.v * dt + 1/2 * a * dt**2
def update_velocity(self, a):
self.v += a*dt # eerst snelheid aanpassen op basis van de acceleratie, anders gaat het deeltje raar doen bij de randen
self.v[self.r<=-10] = -self.v[self.r<=-10] #de snelheid van het deeltje als word in de x of y richting omgedraaid als het buiten de rand op x=-10 of y=-10
self.v[self.r>=10] = -self.v[self.r>=10] #de snelheid van het deeltje als word in de x of y richting omgedraaid als het buiten de rand op x=10 of y=10
# Simulation parameters
dt = 0.1
num_steps = 500
a = np.array([0.0, -5.0])
num_particles = 2
particle_array = [0] * num_particles #een lijst van nullen met een lengte van het aantal deeltjes
#de lijst vullen met deeltjes, waarvan de kleur een vorm van groen is,
# die bepaald woord door het aantal deeltjes
for i in range(num_particles):
particle_array[i] = ParticleClass(m=1.0, v=[0, 0], r=[0.0, 0.0],R=1.0,c=[0,(i+1)/num_particles,0])
particle_array[1].v = np.array([1,0.0]) #snelheid van het tweede deeltje aanpassen
# creeeren van de plot en de assen
fig, ax = plt.subplots()
ax.set_xlim(-10, 10)
ax.set_ylim(-10, 10)
ax.set_aspect('equal')
ax.set_title("Particle Animation")
ax.set_xlabel("x")
ax.set_ylabel("y")
#aanmaken van lijsten en arrays om te vullen met data
track_array = [0] * num_particles
dot_array = [0] * num_particles
track_x = np.zeros([num_particles,num_steps])
track_y = np.zeros([num_particles,num_steps])
dot, = ax.plot([], [], 'ro', markersize=10);
#track en dot array vullen met een plot
for i in range(num_particles):
track_array[i], = ax.plot([], [], '.', color=particle_array[i].c, markersize=0.8)
dot_array[i], = ax.plot([], [], 'o', color=particle_array[i].c, markersize=10);
# initializeren van onze functie voor de animatie
def init():
#voor alle deeltjes de init uitvoegen
for i in range(num_particles):
dot.set_data([], [])
return tuple(dot_array)
# Update function for each frame
def update(frame):
#voor alle deeltjes de snelheid en positie updaten, de punt plotten, de x en y positie toevoegen aan de track en de track plotten
for n, particle in enumerate(particle_array):
particle.update_velocity(a)
particle.update_position()
dot_array[n].set_data([particle.r[0]], [particle.r[1]])
track_x[n, frame] = particle.r[0]
track_y[n, frame] = particle.r[1]
track_array[n].set_data(track_x[n], track_y[n])
return tuple(dot_array) + tuple(track_array) #de dot_array en track_array returne als een tuple
# Create animation
ani = FuncAnimation(fig, update, frames=range(200), init_func=init, blit=True, interval=50)
# For Jupyter notebook:
from IPython.display import HTML
HTML(ani.to_jshtml())

We waren gebleven bij het maken van een botsingsmodel, waarbij we nu twee deeltjes hebben die onderhevig zijn aan zwaartekracht.
Laten we de zwaartekracht even vergeten en alleen 1D kijken.
# Define a class for a particle
# Maken van de class met botsing
class ParticleClass:
def __init__(self, m, v, r, R, c):
self.m = m
self.v = np.array(v, dtype=float)
self.r = np.array(r, dtype=float)
self.R = np.array(R, dtype=float)
self.c = c
def update_position(self):
self.r += self.v * dt
self.v[self.r<=-10] = -self.v[self.r<=-10] #de snelheid van het deeltje als word in de x of y richting omgedraaid als het buiten de rand op x=-10 of y=-10
self.v[self.r>=10] = -self.v[self.r>=10] #de snelheid van het deeltje als word in de x of y richting omgedraaid als het buiten de rand op x=10 of y=10
def collide_detection(self, other):
return (self.r[0]-other.r[0])**2+(self.r[1]-other.r[1])**2 < (self.R + other.R)**2 #als |r_1-r_2|^2 < (2R)^2 geld returnd deze functie True en anders False
# Simulation parameters
dt = 0.1 # time step
num_steps = 200 # number of time steps
num_particles = 2
vx = [1,-2.5] #array met de snelheid in de x richting voor de deeltjes
x = [-2,0] #array met de startposity op de x-as voor de deeltjes
particle_array = [0] * num_particles #een lijst van nullen met een lengte van het aantal deeltjes
# de lijst vullen met deeltjes, waar de snelheid en positie in de x richting uit de vx en x lijsten worden gehaald.
# De kleur is een vorm van groen is, die bepaald woord door het aantal deeltjes
for i in range(num_particles):
particle_array[i] = ParticleClass(m=1.0, v=[vx[i], 0], r=[x[i], 0],R=0.45,c=[0,(i+1)/num_particles,0])
# Creer de plot
fig, ax = plt.subplots()
ax.set_xlim(-10, 10)
ax.set_ylim(-10, 10)
ax.set_aspect('equal')
ax.set_title("Particle Animation")
ax.set_xlabel("x")
ax.set_ylabel("y")
track_array = [0] * num_particles
dot_array = [0] * num_particles
track_x = np.zeros([num_particles,num_steps])
track_y = np.zeros([num_particles,num_steps])
for i in range(num_particles):
track_array[i], = ax.plot([], [], '.', color=particle_array[i].c, markersize=0.8)
dot_array[i], = ax.plot([], [], 'o', color=particle_array[i].c, markersize=10);
# Initaliseren voor de animatie
def init():
#voor alle deeltjes de init uitvoegen
for n, dot in enumerate(dot_array):
dot.set_data([], [])
return tuple(dot_array)
# Updaten van de functie per frame
def update(frame):
#voor alle deeltjes de snelheid en positie updaten, de punt plotten, de x en y positie toevoegen aan de track en de track plotten
for n, particle in enumerate(particle_array):
particle.update_position()
dot_array[n].set_data([particle.r[0]], [particle.r[1]])
track_x[n, frame] = particle.r[0]
track_y[n, frame] = particle.r[1]
track_array[n].set_data(track_x[n], track_y[n])
for l in list(itertools.combinations(range(len(particle_array)),2)): #een for loop door de een lijst met unieke sets van 2 indexen van de particle array
#als tussent de twee deeltjes een collision plaats vind worden de snelheden van de deeltjes omgedraaid
if particle_array[l[0]].collide_detection(particle_array[l[1]]):
v_0_copy = particle_array[l[0]].v #snelheid van particle_0 opslaan, aangezien deze nodig is voor het berekenen van de snelheid van particle_1 nadat de snelheid van particle_0 al aangepast is
#snelheid na de botsing berekenen volgens de vergelijking v_0=((m_0-m_1)u_0 + 2m_1v_1)/(m_1 + m_2) en v_1=((m_1-m_0)u_1 + 2m_0v_0)/(m_1 + m_2)
particle_array[l[0]].v = ((particle_array[l[0]].m - particle_array[l[1]].m)*particle_array[l[0]].v + 2*particle_array[l[1]].m*particle_array[l[1]].v)/(particle_array[l[0]].m + particle_array[l[1]].m)
particle_array[l[1]].v = (2*particle_array[l[0]].m*v_0_copy + 2*(particle_array[l[1]].m - particle_array[l[0]].m)*particle_array[l[1]].v)/(particle_array[l[0]].m + particle_array[l[1]].m)
return tuple(dot_array) + tuple(track_array) #de dot_array en track_array returne als een tuple
# Creeer animatie
ani = FuncAnimation(fig, update, frames=range(num_steps), init_func=init, blit=True, interval=50)
# Voor Jupyter notebook:
from IPython.display import HTML
HTML(ani.to_jshtml())
Terug naar ons vraagstuk... we willen een simulatie waarbij een deeltje met een massa en snelheid op een andere stilstaand deeltje met massa botst. Deeltje twee beweegt naar een muur, botst tegen de muur en beweegt richting deeltje 1 en botst tegen dit deeltje. Hoe vaak vindt deze botsing plaats als functie van de massa verhouding ?
Daarvoor moeten we even terug naar het botsingsmodel zoals geleerd in Klassieke Mechanica. Bij elastische botsingen is zowel het impulsmoment als de kinetische energie behouden.
Voor een botsing met twee deeltjes levert dit een analytische oplossing:
we vragen je natuurlijk niet om deze vergelijking zelf te schrijven in Python, maar die vergelijking operationaliseren we hieronder wel.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
class ParticleClass:
def __init__(self, m, v, r, R):
self.m = m # mass of the particle
self.v = np.array(v, dtype=float) # velocity vector
self.r = np.array(r, dtype=float) # position vector
self.R = np.array(R, dtype=float) # radius of the particle
def update_position(self):
self.r += self.v * dt
def collide_detection(self, other):
return np.linalg.norm(self.r - other.r) <= (self.R + other.R)
# Simulation parameters
dt = 0.1 # time step
num_steps = 530 # number of time steps
m1 = 1.0
m2 = 100.0
particleA = ParticleClass(m=m1, v=[0, 0], r=[-4.0, 0.0],R=0.45)
particleB = ParticleClass(m=m2, v=[-1, 0], r=[-2.0, 0.0],R=0.45)
# Create the figure and axis
fig, ax = plt.subplots()
ax.set_xlim(-10, 10)
ax.set_ylim(-10, 10)
ax.set_aspect('equal')
ax.set_title("Particle Animation")
ax.set_xlabel("x")
ax.set_ylabel("y")
dot, = ax.plot([], [], 'ro', markersize=10); # semicolon to suppress output
counter = 0 #counter op 0 zetten
# Create the particle as a red dot
dotA, = ax.plot([], [], 'ro', markersize=10)
dotB, = ax.plot([], [], 'bo', markersize=10)
counter_text = ax.text(-9.5, 9, "")
# Initialization function for animation
def init():
dot.set_data([], [])
return dot,
# Update function for each frame
def update(frame):
global counter #counter een global variable maken
particleA.update_position()
particleB.update_position()
dotA.set_data([particleA.r[0]], [particleA.r[1]])
dotB.set_data([particleB.r[0]], [particleB.r[1]])
counter_text.set_text(f"Collisions: {counter}")
#collision detection and response
if particleA.collide_detection(particleB):
vA, vB, mA, mB, rA, rB = particleA.v, particleB.v, particleA.m, particleB.m, particleA.r, particleB.r
vA_new = vA - 2 * mB / (mA + mB) * np.dot(vA - vB, rA - rB) / (1e-12+np.linalg.norm(rA - rB))**2 * (rA - rB)
vB_new = vB - 2 * mA / (mA + mB) * np.dot(vB - vA, rB - rA) / (1e-12+np.linalg.norm(rB - rA))**2 * (rB - rA)
particleA.v = vA_new
particleB.v = vB_new
counter += 1 #als er een botsing tussen de deeltjes plaats vind gaat de counter 1 omhoog
#your code/answer
# wall collision detection and response
if particleA.r[0]**2>100: # Check if particle is outside the bounds, np.abs could be used but is slower
particleA.v[0] = -particleA.v[0]
counter += 1 #als er een botsing met de rand plaats vind gaat de counter 1 omhoog
#your code/answer
if particleA.r[1]**2>100:
particleA.v[1] = -particleA.v[1]
counter += 1 #als er een botsing met de rand plaats vind gaat de counter 1 omhoog
#your code/answer
dot.set_data([particleB.r[0]], [particleB.r[1]])
if particleB.r[0]**2>100:
particleB.v[0] = -particleB.v[0]
counter += 1 #als er een botsing met de rand plaats vind gaat de counter 1 omhoog
#your code/answer
if particleB.r[1]**2>100:
particleB.v[1] = -particleB.v[1]
counter += 1 #als er een botsing met de rand plaats vind gaat de counter 1 omhoog
#your code/answer
return dot, counter_text
# Create animation
ani = FuncAnimation(fig, update, frames=range(200), init_func=init, blit=True, interval=50)
# For Jupyter notebook:
from IPython.display import HTML
HTML(ani.to_jshtml())