Ising.java


Below is the syntax highlighted version of Ising.java from §9.8 Data Analysis.


/******************************************************************************
 *  Compilation:  javac Ising.java
 *  Execution:    java Ising N kT
 *  
 *  Create an N-by-N grid of sites. Each site has spin "up" (+1)
 *  or "down" (-1).
 * 
 *  % java Ising N 2.26918  // critical temperature
 *
 ******************************************************************************/

import java.awt.Color;

public class Ising {
    private int N;                  // N-by-N grid of sites
    private double J = 1.0;         // strength of spin-spin interaction (feromagentic when J is positive)
    private double kT;              // temperature (say between 1 and 4)
    private boolean[][] spin;       // up (true) or down (false)

    // N-by-N grid, kT = temperature, p = prob of up spin
    public Ising(int N, double kT, double p) {
        this.N    = N;
        this.kT   = kT;
        this.spin = new boolean[N][N];

        // initialize at random
        for (int i = 0; i < N; i++)
            for (int j = 0; j < N; j++)
                spin[i][j] = (Math.random() < p);
    }


    // total average magnetization (between -1 and 1)
    public double magnetization() {
        int M = 0;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if (spin[i][j]) M++;
                else            M--;
            }
        }
        return 1.0 * M / (N * N);
    }

    // total energy of site (i, j), using periodic boundary conditions
    // assumes 0 <= i, j < N
    private double energy(int i, int j) {
        double E = 0.0;
        if (spin[i][j] == spin[(i+1)%N][j])   E++;
        else                                  E--;
        if (spin[i][j] == spin[i][(j+1)%N])   E++;
        else                                  E--;
        if (spin[i][j] == spin[(i-1+N)%N][j]) E++;
        else                                  E--;
        if (spin[i][j] == spin[i][(j-1+N)%N]) E++;
        else                                  E--;
        return -J * E;
    }

    // total energy, using periodic boundary conditions
    public double energy() {
        double E = 0.0;
        for (int i = 0; i < N; i++)
            for (int j = 0; j < N; j++)
                E += 0.5 * energy(i, j);  // divide by two to mitigate double-counting
        return E;
    }

    // one Monte Carlo step
    public void step(int i, int j) {
        double deltaE = -2 * energy(i, j);
        // flip if energy decreases or get lucky
        if ((deltaE <= 0) || (Math.random() <= Math.exp(-deltaE / kT)))
            spin[i][j] = !spin[i][j];
    }

    // one Monte Carlo phase - N^2 steps
    public void phase() {
        for (int steps = 0; steps < N*N; steps++) {
            int i = (int) (Math.random() * N);
            int j = (int) (Math.random() * N);
            step(i, j);
        }
    }

    // plot it
    public void draw() {
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if (spin[i][j]) StdDraw.setPenColor(StdDraw.WHITE);
                else            StdDraw.setPenColor(StdDraw.BLUE);
                StdDraw.filledSquare(i + 0.5, j + 0.5, .5);
            }
        }

        // draw lines
        StdDraw.setPenColor(StdDraw.BLACK);
        for (int i = 0; i < N; i++) {
            StdDraw.line(i, 0, i, N);
            StdDraw.line(0, i, N, i);
        }
    }

    // string representation
    public String toString() {
        String NEWLINE = System.getProperty("line.separator");
        String s = "";
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if (spin[i][j]) s += "< ";
                else            s += "> ";
            }
            s += NEWLINE;
        }
        return s;
    }



    public static void main(String[] args) {
        int N = Integer.parseInt(args[0]);          // N-by-N lattice
        double kT = Double.parseDouble(args[1]);    // temperature
        Ising ising = new Ising(N, kT, 0.5);

        // set scale and turn on animation mode
        StdDraw.setXscale(0, N);
        StdDraw.setYscale(0, N);
        StdDraw.enableDoubleBuffering();

        for (int t = 0; true; t++) {
            ising.phase();
            ising.draw();
            StdDraw.show();
            StdDraw.pause(50);
        }
   }

}


Copyright © 2000–2017, Robert Sedgewick and Kevin Wayne.
Last updated: Fri Oct 20 14:12:12 EDT 2017.