Simulation of a double slit experiment with acoustic waves

When a planar wave goes through a small opening, the wave is refracted, acting as a point wave at the location of the slit. In this simulation we see also the interference of the planar wave with its own reflection.


In [1]:
from __future__ import print_function, division
import lambdasim as l
import shapelib as sh
import os
from IPython.display import *

%matplotlib inline

Set the environment for the simulation

A Simulation is defined by a regular matrix and a resolution to match it to real-world dimensions. Here we define a simulation space of 5,33m x 3m with a spatial resolution of 6mm and a time resolution of 0.01 ms (the time resolution depends on the propagation time of our medium)


In [2]:
# Create dimension to fit standard video sizes
Ypix = 480   
Xpix = int(Ypix * 16/9. +0.5)
Y = 3. # in meters

s = l.Simulation(resolution=Y/Ypix)
s.set_size_in_pixels(Xpix, Ypix)
X, Y = s.size()

wall_y     = Y*0.25  # the position of the slit, relative to the size of the canvas
wall_width = 0.03    # the with of the wall, in m (3cm)
source_y   = 0.05    # the position of the source, in meters
source_width = X*0.4 # the width of the source (a planar source)
source_freq = 1000   # Hz
source_amp  = 0.3    # Pa

slit_width = max(l.acoustics.freq2wavelen(source_freq)/4, 5*s.nodesize)
slit_dist  = min(l.acoustics.freq2wavelen(source_freq)*2, source_width*0.9)

print(s)
print("slit width:", slit_width)


Adjusting pixel size: X 853 -> 854
Simulation
----------
nodesize    : 6 mm
samplerate  : 77612 Hz
C           : 343.0 m/s
rho         : 1.204 kg/m3
size        : 5.34 m x 3.00 m
matrix      : 854 pixels x 480 pixels
num. sources: 0
slit width: 0.0857855717035

Walls and slits

We want to work on the real-world dimensions and leave the rasterization of the space as an implementation detail, so that we can increase the resolution when needed, without having to redefine the simulation. That's why all operations are done with "geometries", which have infinite resolution, and only at the end we rasterize it to the underlying matrix (this is done with .wall_from_geometry). Also, since we are working with analytical shapes, it is very easy to calculate dead nodes and angles, which increase both throughput and resolution of the simulation.


In [4]:
wall = sh.box(0, wall_y-wall_width*0.5, X, wall_y+wall_width*0.5)

def makeslit(wall, x, y, width, height=1):
    slit = sh.box(x - width*0.5, y-height*0.5, x+width*0.5, y+height*0.5)
    wall = wall.difference(slit)
    return wall

wall = makeslit(wall, X*0.5 - slit_width*0.5 - slit_dist*0.5, wall_y, slit_width)
wall = makeslit(wall, X*0.5 + slit_width*0.5 + slit_dist*0.5, wall_y, slit_width)

# sidewalls
wall = wall.union(sh.box(0, 0, X*0.5-source_width*0.5, wall_y))
wall = wall.union(sh.box(X*0.5+source_width*0.5, 0, X, wall_y))

s.wall_from_geometry(wall)
sh.geom_plot(wall, yrange=(0, Y))


cols: 854, rows: 480
using backend: rasterio

Create the source

The source is a plane wave (sine) perpendicular to the slits


In [5]:
linesource = sh.line(X*0.5-source_width*0.5, source_y, X*0.5+source_width*0.5, source_y)
source = s.source_from_geometry(linesource, 'sin', amp=source_amp, freq=source_freq)
print(source)


cols: 854, rows: 480
using backend: rasterio
SourceList
----------

numpoints: 342
freqs    : set([1000])
coords   : (256, 471) - (597, 471)

Write and plot the simulation


In [6]:
xpix, ypix = s.size_in_pixels()
s.write("twoslit{x}x{y}.sim".format(x=xpix, y=ypix))
s.plot()


Open the simulation for visualization

This will open the Lambda app with our simulation. For that you need to have the app installed in your system. See https://github.com/gesellkammer/lambda/releases


In [9]:
proc = s.opensim(vis=True, cmap=2, contrast=72)


Calling Lamda as: ['/Applications/Lambda.app/Contents/MacOS/Lambda', '-file', '/Users/em/proj/simulations/twoslit/twoslit854x480.sim', '-vis', '-walls', '-contrast', '72', '-colormap', '2']

In [10]:
proc, videopath = s.render_video(duration=40/1000., contrast=76, cmap=2, walls=True, fps=60)


Calling Lamda as: ['/Applications/Lambda.app/Contents/MacOS/Lambda', '-avi', '-exit', '-file', '/Users/em/proj/simulations/twoslit/twoslit854x480.sim', '-contrast', '76', '-quality', '100', '-avifps', '60', '-walls', '-iterations', '3108', '-colormap', '2']

After converting to .webm and uploading, this is the resulting video


In [21]:
from IPython.display import HTML
HTML("""
<video controls>
<source src="https://dl.dropboxusercontent.com/u/264776/web/lambda/twoslit854x480.webm">
</video>
""")


Out[21]:

In [ ]: