PHY 411-506 Home Home  |  Course Outline  |  Lectures  |  Homework  |  Files

Lecture 11: February 9


Modified Random Walks: A Lattice Gas

Chapter 12 discusses several modifications of the simple random walk with fixed step size. An interesting variant is particle diffusion in a lattice gas. The following applet is generated by the program LatticeGas.java, which is a translation of PROGRAM lattice_gas on page 380:

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:

Self-Avoiding Random Walk in 2 Dimensions

We next study the application to polymers in §12.3. Here is a simulation SelfAvoidingWalk.java of the self-avoiding random walk in 2 dimensions described in Problem 12.12:

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);
    }
}


UB Physics Home Questions or comments: phygons@acsu.buffalo.edu