Assignment 6: Off-lattice simulation of the hard-disk fluid
in 2-d
Write a Monte Carlo code for a system of 225 disks confined
within a box of size 40x40. Each disk has radius 1, which means they overlap if
their center-to-center separation is less than 2.
Option 1: use periodic boundary conditions, and calculate
both g(r) and mean square displacement vs time. For g(r),
use concentric circles with spacing of 0.2 between them.
Option 2: use hard boundaries; calculate density as a function
of x near the hard wall, using x-increments of size 0.2. Calculate also the
mean square displacement as a function of time.
Note: the fact that rmax is
fluctuating means that your mean square displacement may not be linear. However
its continued growth is a sign that the system is in a fluid state and is not a
glass.
Here is a meta-code to get you started. Details are included
for calculating the pair correlation function.
Set up
data structures
n=225
number of particles
nsteps=100000 number of monte carlo steps
define
arrays x(n),y(n) these are particle positions
define
arrays dx(n),dy(n) these
are particle displacements from initial
positions
Data
structures for the cell list
define
array num(20,20) counts how many particles are in
cell number icell,jcell
define
array clist(20,20,10) lists the particles contained
in
cell number icell,jcell
define
some real variables: dxcell=2.,dycell=2. these are cell sizes
define
some integer variables: nxcells=20,nycells=20 number
of cells in
x,y,
directions
define
some real variables:
hx=40,hy=40 these are
my cell dimensions
rmax=1.0 this is my
initial max step size for mc steps
theta this is a random angle for mc steps
rho0 this is the
average number density of particles, = n/(hx*hy)
pi=4.*atan(1.0), twopi=pi*2.0
define
variables for calculating g(r)
dr=0.2 spacing of
concentric circles
if we go out to a
distance of r=10 that gives us 50 circles
define real array
g(50), this is g(r) for the current configuration
define real array gsave(50), a running average of g(r) over time
define integer
array kount(50) counts how many particle pairs are
separated by a given distance
define integer kountg counts how
many configs of g(r) are included in our running average
initialize the random
number generator with a seed of your choice
iseed=5628901
call srand(iseed)
open a data file called r2ms.dat to store mean square
displacement vs time
zero out dx(n),dy(n) arrays
zero out g(50),gsave(50),
and set kountg=0
set up initial
configuration by putting particles at the sites of a 15x15 lattice with spacing 2.66
k=0
do 1 ii=1,15
do 2
jj=1,15
k=k+1
x(k)=ii*2.66
y(k)=jj*2.66
2
continue
1
continue
Loop on istep=1 to nsteps
refresh the cell list
do 50
i=1,nxcells
do 51
j=1,nycells
num(i,j)=0
do 52 k=1,10
clist(i,j,k)=0
52 continue
51 continue
50 continue
do 60
i=1,n
icell=1+x(i)/dxcell
jcell=1+y(i)/dycell
num(icell,jcell)=num(icell,jcell)+1
clist(icell,jcell,num(icell,jcell))=i
60
continue
set naccept=0
Loop itry=1,n
pick a particle ip at random between 1 and n, save its x and y positions
figure out what cell
it's in: icellold, jcellold
pick a random step
size r between 0 and rmax
pick a random angle
theta between 0 and twopi
move particle ip
if it went outside
the periodic boundaries, add or subtract the boxsize to
get it back in bounds
figure out what cell
it's in now, call that icell,jcell
if not the same cell,
add the particle to its new cell
num(icell,jcell)=num(icell,jcell)+1
clist(icell,jcell,num(icell,jcell))=ip
CHECK for overlaps:
step 1: loop on ic0=icell-1 to icell+1
ic=ic0
if ic<1 then ic=ic+nxcells
if ic>nxcells then ic=ic-nxcells
step 2: loop on jc0=jcell-1 to jcell+1
jc=jc0
if jc<1 then jc=jc+nycells
if jc>nycells then jc=jc-nycells
are there any particles in cell ic,jc?
if so, loop over them, k=1,num(ic,jc)
jp=clist(ic,jc,k)
if ip and jp
aren't the same particle, calculate the distance squared between them using
periodic bc's
if the distance squared is less than 4, there is an overlap,
so put particle ip back where it was before, and go
to next itry.
next k
next jc0
next ic0
made it all
the way through with no overlaps, it's a success, hurray! naccept=naccept+1
add new step
to the displacement arrays
dx(ip)=dx(ip)+r*cos(theta)
dy(ip)=dy(ip)+r*sin(theta)
next itry
check
acceptance rate and adjust rmax as needed
lower rate
threshold is 15%, upper rate threshold is 25%
if istep=100,200,300.... then let's
print some data and make some
measurements
open a data file
disk1.dat, dump x(i),y(i)
for the current config
find the mean
square displacement from your arrays dx(n),dy(n),
and write it into
the data file r2ms.dat
calculate the
pair correlation function in the present
configuration and
add it to the running average. Here is my fortran
code for this part. First, zero out the kount(50)
and g(50) arrays
do 499
ir=1,50
kount(ir)=0
g(ir)=0.d0
499 continue
Now, loop on all pairs, calculate
distance between, convert it to an integer ir, and
increment kount(ir) by one.
do 500
i=1,n-1
do 501 j=i+1,n
ddx=dabs(x(i)-x(j))
ddx=min(ddx,hx-ddx)
ddy=dabs(y(i)-y(j))
ddy=min(ddy,hy-ddy)
r=dsqrt(ddx*ddx+ddy*ddy)
ir=1+int(r/dr)
kount(ir)=kount(ir)+1
501 continue
500
continue
Now
normalize g(ir) by the area
between the outer and inner circles. There are several other factors which we
can talk about in class.
Accumulate
a running sum of g(50) in the array gsave(50). Increment
kountg by one for every configthat
goes into the running average.
g.dat
is the g(r) for the current config only
gsave.dat
is the average g(r) over the whole run
open(unit=16,file='g.dat',status='unknown')
open(unit=17,file='gsave.dat',status='unknown')
kountg=kountg+1
do
510 ir=1,50
r1=(ir-1)*dr
r2=ir*dr
area=pi*(r2*r2-r1*r1)
g(ir)=float(kount(ir))/area
g(ir)=g(ir)/rho0
g(ir)=g(ir)*2.d0
g(ir)=g(ir)/float(n)
write(16,*)r2,g(ir)
gsave(ir)=gsave(ir)+g(ir)
write(17,*)r2,gsave(ir)/float(kountg)
510
continue
close(unit=16)
close(unit=17)
next istep
close data files
all done!