Home
|
Course Outline
|
Lectures
|
Homework
|
Files
Here is the code which generates this applet:
// LatticeGas.java
import comphys.*;
import comphys.graphics.*;
public class LatticeGas extends Animation {
int L = 40; // linear dimension of lattice
int N = 500; // number of particles
int t, tmax = 50; // Number of Monte Carlo steps per particle
boolean[][] occupied; // L x L lattice
int[] x, y; // coordinates of occupied sites
int[] x0, y0; // coordinates of occupied sites at t = 0
double R2bar, oldR2bar; // mean squared displacement
void initial () {
if (occupied == null || occupied.length < L) {
occupied = new boolean[L][L];
}
if (x == null || x.length < N) {
x = new int[N];
y = new int[N];
x0 = new int[N];
y0 = new int[N];
}
lattice();
t = 0;
R2bar = oldR2bar = 0;
}
void lattice () {
for (int iy = 0; iy < L; iy++)
for (int ix = 0; ix < L; ix++)
occupied[ix][iy] = false;
int i = 0;
do {
int xadd = (int) (Math.random() * L);
int yadd = (int) (Math.random() * L);
if (!occupied[xadd][yadd]) {
++i;
occupied[xadd][yadd] = true;
x[i] = x0[i] = xadd;
y[i] = y0[i] = yadd;
}
} while (i < N - 1);
}
int xtrial, ytrial;
void move () {
for (int n = 0; n < N; n++) {
int i = (int) (Math.random() * N);
xtrial = x[i];
ytrial = y[i];
direction();
if (!occupied[xtrial][ytrial]) {
occupied[x[i]][y[i]] = false;
x[i] = xtrial;
y[i] = ytrial;
occupied[xtrial][ytrial] = true;
}
}
}
void direction () {
int dir = (int) (Math.random() * 4) + 1;
switch (dir) {
case 1:
++xtrial;
if (xtrial >= L)
xtrial = 0;
break;
case 2:
--xtrial;
if (xtrial < 0)
xtrial = L - 1;
break;
case 3:
++ytrial;
if (ytrial >= L)
ytrial = 0;
break;
case 4:
--ytrial;
if (ytrial < 0)
ytrial = L - 1;
}
}
void data () {
oldR2bar = R2bar;
double R2 = 0;
for (int n = 0; n < N; n++) {
double dx = separation(x[n], x0[n]);
double dy = separation(y[n], y0[n]);
R2 += dx * dx + dy * dy;
}
R2bar = R2 / N;
}
double separation (double x, double x0) {
double dx = x - x0;
// use periodic boundary conditions
if (Math.abs(dx) > L / 2.0) {
if (dx > 0)
dx -= L;
else
dx += L;
}
return dx;
}
class Lattice extends Plot {
Lattice () {
setSize(300, 300);
}
public void paint () {
setWindow(0, L - 1, 0, L - 1);
clear();
setColor("yellow");
boxArea(0, L - 1, 0, L - 1);
setColor("blue");
for (int iy = 0; iy < L; iy++) {
for (int ix = 0; ix < L; ix++)
if (occupied[ix][iy])
boxArea(ix, ix + 1, iy, iy + 1);
}
}
}
boolean needToClear = true;
class Graph extends Plot {
Graph () {
setSize(300, 300);
}
public void paint () {
if (needToClear) {
clear();
setColor("black");
drawAxes(0, tmax, 0, L / 2);
needToClear = false;
setColor("green");
plotStringCenter("Plot of versus t",
0.5 * tmax, L / 2 + 0.02 * L);
}
setColor("red");
if (t > 0)
plotLine(t - 1, oldR2bar, t, R2bar);
setColor("red");
plotPoint(t, R2bar);
plotOverlay();
setColor("red");
plotStringLeft(" = " + Easy.format(R2bar, 6),
tmax, 0.15 * L);
setColor("blue");
plotStringCenter("t=" + t, t, - 0.04 * L);
setColor("magenta");
if (t > 0)
plotStringLeft("D = " + Easy.format(R2bar / (4 * t), 6),
tmax, 0.1 * L);
}
}
Lattice lattice;
Graph graph;
Reader LReader, NReader, tmaxReader;
public void init () {
initial();
add(lattice = new Lattice());
add(graph = new Graph());
add(LReader = new Reader("L = ", L));
add(NReader = new Reader("N = ", N));
add(tmaxReader = new Reader("t_max = ", tmax));
addControlPanel();
lattice.repaint();
graph.repaint();
}
public void step () {
++t;
if (t > tmax) {
stopAnimation();
return;
}
move();
lattice.repaint();
data();
graph.repaint();
}
public void reset () {
L = LReader.readInt();
N = NReader.readInt();
tmax = tmaxReader.readInt();
initial();
lattice.repaint();
needToClear = true;
graph.repaint();
}
public static void main (String[] args) {
LatticeGas latticeGas = new LatticeGas();
latticeGas.frame("Diffusion in a Lattice Gas", 700, 500);
}
}
Note the following features of this program:
public class LatticeGas extends Animation {
class Lattice extends Plot {
Lattice () {
setSize(300, 300);
}
public void paint () {
setWindow(0, L - 1, 0, L - 1);
}
}
class Graph extends Plot {
Graph () {
setSize(300, 300);
}
public void paint () {
if (needToClear) {
drawAxes(0, tmax, 0, L / 2);
}
}
}
Lattice lattice;
Graph graph;
public void init () {
add(lattice = new Lattice());
add(graph = new Graph());
}
public static void main (String[] args) {
LatticeGas latticeGas = new LatticeGas();
}
}
class Lattice and class Graph both extend
comphys.graphics.plot. Note the use of constructor methods
in each case to change the size of each plot (the default size is
400 x 400 in pixel units). Note also the use of the setWindow
and drawAxes methods which allow use of physical units instead
of pixel units in the various plotting methods.
Here is the code which generates this applet:
// SelfAvoidingWalk.java
import comphys.Easy;
import comphys.graphics.*;
public class SelfAvoidingWalk extends Animation {
int L = 30; // max extent of walk in each direction
boolean[][] beenHere; // keep track of sites visited
int N = 10; // desired length of walk
int xWalker, yWalker; // current position of walker
int xPrevious, yPrevious; // previous postition of walker
int n; // number of steps in walk
boolean success; // succeeded in constructing polymer
boolean oops; // self intersection
int nWalks; // number of walks
int nPolymers; // number of polymers constructed
double RsquaredSum; // average end-to-end distance
void initial () {
if (beenHere == null || beenHere.length < L) {
beenHere = new boolean[L][L];
}
for (int x = 0; x < L; x++)
for (int y = 0; y < L; y++)
beenHere[x][y] = false;
xWalker = yWalker = L / 2; // origin at center of lattice
xPrevious = yPrevious = L / 2;
beenHere[xWalker][yWalker] = true;
n = 0;
success = oops = false;
++nWalks;
}
void trialStep () {
int xTrial, yTrial;
do {
xTrial = xWalker;
yTrial = yWalker;
int dir = (int) (4 * Math.random());
switch (dir) {
case 0: xTrial += 1; break;
case 1: xTrial -= 1; break;
case 2: yTrial += 1; break;
case 3: yTrial -= 1; break;
}
} while (xTrial == xPrevious && yTrial == yPrevious);
if ( xTrial < 0 || xTrial >= L ||
yTrial < 0 || yTrial >= L ||
beenHere[xTrial][yTrial] )
oops = true;
xPrevious = xWalker;
yPrevious = yWalker;
xWalker = xTrial;
yWalker = yTrial;
if (!oops) {
beenHere[xWalker][yWalker] = true;
++n;
}
if (n == N) {
++nPolymers;
double x = xWalker - L / 2;
double y = yWalker - L / 2;
RsquaredSum += x * x + y * y;
success = true;
}
}
boolean needToClear;
class Walk extends Plot {
public void paint () {
if (needToClear) {
clear();
setWindow(0, L, 0, L);
setColor("blue");
for (int x = 0; x < L; x++)
for (int y = 0; y < L; y++)
plotPoint(x, y);
needToClear = false;
setColor("green");
}
if (oops)
setColor("red");
plotLine(xWalker, yWalker, xPrevious, yPrevious);
}
}
class Output extends Plot {
Output () {
setSize(400, 30);
}
public void paint () {
setWindow(0, 12, 0, 3);
clear();
setColor("blue");
plotString("Polymers = " + nPolymers, 1, 1);
double RsquaredAverage = RsquaredSum;
if (nPolymers > 0)
RsquaredAverage /= nPolymers;
plotStringCenter(" = " + Easy.format(RsquaredAverage, 4),
6, 1);
double successPercent = 100.0 * nPolymers;
if (nWalks > 0)
successPercent /= nWalks;
plotStringLeft("success% = " + Easy.format(successPercent, 2),
11, 1);
}
}
Walk walk;
Output output;
Reader NReader, LReader;
public void init () {
initial();
needToClear = true;
add(walk = new Walk());
add(output = new Output());
add(NReader = new Reader("N = ", N));
add(LReader = new Reader("L = ", L));
addControlPanel();
}
public void step () {
if (oops || success) {
needToClear = true;
initial();
}
trialStep();
walk.repaint();
output.repaint();
}
public void reset () {
needToClear = true;
nPolymers = nWalks = 0;
RsquaredSum = 0;
N = NReader.readInt();
L = LReader.readInt();
initial();
walk.repaint();
output.repaint();
}
public static void main (String[] args) {
SelfAvoidingWalk saw = new SelfAvoidingWalk();
saw.frame("Self Avoiding Walk", 500, 600);
}
}