This is a model of the pressure in a cubic box for an ideal gas. By running the simulation, we will see that Boyle's law, $$ \\P \propto \frac{1}{V}$$ holds true for an ideal gas.
First, we will import a module containing the classes for this simulation, pycav.mechanics, along with some modules for plotting:
#NAME: Kinetic Theory of Gases
#DESCRIPTION: Collisional and collisionless gases within a confined volume macroscopic properties e.g. pressure observed.
%matplotlib notebook
from pycav.mechanics import *
from vpython import *
import numpy as np
import matplotlib.pyplot as plt
First, we will create an empty array of pressures and volumes, to which we will add the results of our simulations
pressures = []
volumes = []
A graph to plot the average pressure against steps taken is then made and the canvas in which the simulation will run are defined. Next, we define a container for the gas to be in, and we define a system composed of that container with 40 particles in it, which will be displayed in the canvas just made. The simulation is then run with different box sizes. Once this cell is done, execute the last cell to see the relationship that we find between P and V.
scene1 = canvas(title='Gas in a box simulation')
graph1 = graph(x=0, y=0,
xtitle='steps', ytitle='Average pressure',
foreground=color.black, background=color.white,
xmax=1000, xmin=200)
dimension = 0.5
container = Container(dimension)
system = System(collides = False, interacts = False, visualize = True, record_pressure = True, canvas = scene1, container = container)
system.create_particles_in_container(number = 40, speed = 1, radius = 0.03)
while dimension <= 10:
system.pressure_history = []
container.dimension = dimension
dt = 1E-2
f1 = gcurve(color=color.cyan)
system.steps = 0
while system.steps <= 1000:
rate(150)
system.simulate(dt)
f1.plot(system.steps, system.pressure)
pressures.append(system.pressure)
volumes.append(dimension**3)
dimension += 0.75
--------------------------------------------------------------------------- KeyboardInterrupt Traceback (most recent call last) <ipython-input-3-fdd5e7145db5> in <module>() 16 while system.steps <= 1000: 17 rate(150) ---> 18 system.simulate(dt) 19 f1.plot(system.steps, system.pressure) 20 pressures.append(system.pressure) /Applications/anaconda/lib/python3.5/site-packages/pycav/mechanics.py in simulate(self, dt) 887 # Update visualisation 888 if self.visualize: --> 889 self.update_vis() 890 self.time += dt 891 self.steps += 1 /Applications/anaconda/lib/python3.5/site-packages/pycav/mechanics.py in update_vis(self) 712 # Update display of particles(rendered as spheres) 713 for (index, __) in enumerate(self.spheres): --> 714 self.spheres[index].pos = vector_from(self.particles[index].pos) 715 if self.particles[index]._vis_values_changed: 716 self.particles[index]._vis_values_changed = False /Applications/anaconda/lib/python3.5/site-packages/pycav/mechanics.py in vector_from(arr) 66 if vpython is None: 67 import vpython ---> 68 return vpython.vector(arr[0], arr[1], arr[2]) 69 70 /Applications/anaconda/lib/python3.5/site-packages/vpython/vector.py in __init__(self, *args) 23 else: 24 raise TypeError('A vector needs 3 components.') ---> 25 self.on_change = self.ignore 26 27 def ignore(self): KeyboardInterrupt:
Finally, once the simulation above is done, we will use the data we found to plot log(P) vs. log(V), and also show the fitted equation. If Boyle's law is correct, we expect to see a relation of $$ \\log(P) \propto -log(V)$$
fitted = np.polyfit(np.log(volumes),np.log(pressures),1)
print ("log(p)=%.6flog(V)+%.6f"%(fitted[0],fitted[1]))
plt.plot(np.log(volumes),np.log(pressures))
plt.ylabel('log(P)')
plt.xlabel('log(V)')
log(p)=-1.028307log(V)+1.264303
<matplotlib.text.Text at 0x10a291160>